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