]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/ARM7_STR71x_IAR/serial/serial.c
Update to MIT licensed FreeRTOS V10.0.0 - see https://www.freertos.org/History.txt
[freertos] / FreeRTOS / Demo / ARM7_STR71x_IAR / serial / serial.c
1 /*\r
2  * FreeRTOS Kernel V10.0.0\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software. If you wish to use our Amazon\r
14  * FreeRTOS name, please do so in a fair use way that does not cause confusion.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
18  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
19  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
20  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
22  *\r
23  * http://www.FreeRTOS.org\r
24  * http://aws.amazon.com/freertos\r
25  *\r
26  * 1 tab == 4 spaces!\r
27  */\r
28 \r
29 /*\r
30         BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER FOR UART0.\r
31 */\r
32 \r
33 /* Library includes. */\r
34 #include "uart.h"\r
35 #include "gpio.h"\r
36 #include "eic.h"\r
37 \r
38 /* Scheduler includes. */\r
39 #include "FreeRTOS.h"\r
40 #include "queue.h"\r
41 \r
42 /* Demo application includes. */\r
43 #include "serial.h"\r
44 \r
45 #define UART0_Rx_Pin                                    ( 0x0001<< 8 )\r
46 #define UART0_Tx_Pin                                    ( 0x0001<< 9 )\r
47 \r
48 #define serINVALID_QUEUE                                ( ( QueueHandle_t ) 0 )\r
49 #define serNO_BLOCK                                             ( ( TickType_t ) 0 )\r
50 \r
51 /* Macros to turn on and off the Tx empty interrupt. */\r
52 #define serINTERRUPT_ON()                               UART0->IER |= UART_TxHalfEmpty\r
53 #define serINTERRUPT_OFF()                              UART0->IER &= ~UART_TxHalfEmpty\r
54 \r
55 /*-----------------------------------------------------------*/\r
56 \r
57 /* Queues used to hold received characters, and characters waiting to be\r
58 transmitted. */\r
59 static QueueHandle_t xRxedChars;\r
60 static QueueHandle_t xCharsForTx;\r
61 \r
62 /*-----------------------------------------------------------*/\r
63 \r
64 /* Interrupt entry point written in the assembler file serialISR.s79. */\r
65 extern void vSerialISREntry( void );\r
66 \r
67 /* The interrupt service routine - called from the assembly entry point. */\r
68 __arm void vSerialISR( void );\r
69 \r
70 /*-----------------------------------------------------------*/\r
71 \r
72 /*\r
73  * See the serial2.h header file.\r
74  */\r
75 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )\r
76 {\r
77 xComPortHandle xReturn;\r
78         \r
79         /* Create the queues used to hold Rx and Tx characters. */\r
80         xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
81         xCharsForTx = xQueueCreate( uxQueueLength + 1, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
82 \r
83         /* If the queues were created correctly then setup the serial port\r
84         hardware. */\r
85         if( ( xRxedChars != serINVALID_QUEUE ) && ( xCharsForTx != serINVALID_QUEUE ) )\r
86         {\r
87                 portENTER_CRITICAL();\r
88                 {\r
89                         /* Setup the UART port pins. */\r
90                         GPIO_Config( GPIO0, UART0_Tx_Pin, GPIO_AF_PP );\r
91                         GPIO_Config( GPIO0, UART0_Rx_Pin, GPIO_IN_TRI_CMOS );\r
92 \r
93                         /* Configure the UART. */\r
94                         UART_OnOffConfig( UART0, ENABLE );\r
95                         UART_FifoConfig( UART0, DISABLE );\r
96                         UART_FifoReset( UART0, UART_RxFIFO );\r
97                         UART_FifoReset( UART0, UART_TxFIFO );\r
98                         UART_LoopBackConfig(UART0, DISABLE );\r
99                         UART_Config( UART0, ulWantedBaud, UART_NO_PARITY, UART_1_StopBits, UARTM_8D );\r
100                         UART_RxConfig( UART0, ENABLE );\r
101 \r
102                         /* Configure the IEC for the UART interrupts. */\r
103                         EIC_IRQChannelPriorityConfig( UART0_IRQChannel, 1 );\r
104                         EIC_IRQChannelConfig( UART0_IRQChannel, ENABLE );\r
105                         EIC_IRQConfig( ENABLE );\r
106                         UART_ItConfig( UART0, UART_RxBufFull, ENABLE );\r
107                 }\r
108                 portEXIT_CRITICAL();\r
109         }\r
110         else\r
111         {\r
112                 xReturn = ( xComPortHandle ) 0;\r
113         }\r
114 \r
115         /* This demo file only supports a single port but we have to return\r
116         something to comply with the standard demo header file. */\r
117         return xReturn;\r
118 }\r
119 /*-----------------------------------------------------------*/\r
120 \r
121 signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )\r
122 {\r
123         /* The port handle is not required as this driver only supports one port. */\r
124         ( void ) pxPort;\r
125 \r
126         /* Get the next character from the buffer.  Return false if no characters\r
127         are available, or arrive before xBlockTime expires. */\r
128         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )\r
129         {\r
130                 return pdTRUE;\r
131         }\r
132         else\r
133         {\r
134                 return pdFALSE;\r
135         }\r
136 }\r
137 /*-----------------------------------------------------------*/\r
138 \r
139 void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )\r
140 {\r
141 signed char *pxNext;\r
142 \r
143         /* A couple of parameters that this port does not use. */\r
144         ( void ) usStringLength;\r
145         ( void ) pxPort;\r
146 \r
147         /* NOTE: This implementation does not handle the queue being full as no\r
148         block time is used! */\r
149 \r
150         /* The port handle is not required as this driver only supports UART0. */\r
151         ( void ) pxPort;\r
152 \r
153         /* Send each character in the string, one at a time. */\r
154         pxNext = ( signed char * ) pcString;\r
155         while( *pxNext )\r
156         {\r
157                 xSerialPutChar( pxPort, *pxNext, serNO_BLOCK );\r
158                 pxNext++;\r
159         }\r
160 }\r
161 /*-----------------------------------------------------------*/\r
162 \r
163 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )\r
164 {\r
165         /* Place the character in the queue of characters to be transmitted. */\r
166         if( xQueueSend( xCharsForTx, &cOutChar, xBlockTime ) != pdPASS )\r
167         {\r
168                 return pdFAIL;\r
169         }\r
170 \r
171         /* Turn on the Tx interrupt so the ISR will remove the character from the\r
172         queue and send it.   This does not need to be in a critical section as\r
173         if the interrupt has already removed the character the next interrupt\r
174         will simply turn off the Tx interrupt again. */\r
175         serINTERRUPT_ON();\r
176 \r
177         return pdPASS;\r
178 }\r
179 /*-----------------------------------------------------------*/\r
180 \r
181 void vSerialClose( xComPortHandle xPort )\r
182 {\r
183         /* Not supported as not required by the demo application. */\r
184 }\r
185 /*-----------------------------------------------------------*/\r
186 \r
187 /* Serial port ISR.  This can cause a context switch so is not defined as a\r
188 standard ISR using the __irq keyword.  Instead a wrapper function is defined\r
189 within serialISR.s79 which in turn calls this function.  See the port\r
190 documentation on the FreeRTOS.org website for more information. */\r
191 __arm void vSerialISR( void )\r
192 {\r
193 unsigned short usStatus;\r
194 signed char cChar;\r
195 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
196 \r
197         /* What caused the interrupt? */\r
198         usStatus = UART_FlagStatus( UART0 );\r
199 \r
200         if( usStatus & UART_TxHalfEmpty )\r
201         {\r
202                 /* The interrupt was caused by the THR becoming empty.  Are there any\r
203                 more characters to transmit? */\r
204                 if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )\r
205                 {\r
206                         /* A character was retrieved from the queue so can be sent to the\r
207                         THR now. */\r
208                         UART0->TxBUFR = cChar;\r
209                 }\r
210                 else\r
211                 {\r
212                         /* Queue empty, nothing to send so turn off the Tx interrupt. */\r
213                         serINTERRUPT_OFF();\r
214                 }               \r
215         }\r
216 \r
217         if( usStatus &  UART_RxBufFull )\r
218         {\r
219                 /* The interrupt was caused by a character being received.  Grab the\r
220                 character from the RHR and place it in the queue of received\r
221                 characters. */\r
222                 cChar = UART0->RxBUFR;\r
223                 xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );\r
224         }\r
225 \r
226         /* If a task was woken by either a character being received or a character\r
227         being transmitted then we may need to switch to another task. */\r
228         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
229 \r
230         /* End the interrupt in the EIC. */\r
231         portCLEAR_EIC();\r
232 }\r
233 \r
234 \r
235 \r
236 \r
237 \r
238         \r