]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/ARM9_STR91X_IAR/serial/serial.c
Update version number in preparation for maintenance release.
[freertos] / FreeRTOS / Demo / ARM9_STR91X_IAR / serial / serial.c
1 /*\r
2     FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.\r
3     All rights reserved\r
4 \r
5     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
6 \r
7     This file is part of the FreeRTOS distribution.\r
8 \r
9     FreeRTOS is free software; you can redistribute it and/or modify it under\r
10     the terms of the GNU General Public License (version 2) as published by the\r
11     Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.\r
12 \r
13     ***************************************************************************\r
14     >>!   NOTE: The modification to the GPL is included to allow you to     !<<\r
15     >>!   distribute a combined work that includes FreeRTOS without being   !<<\r
16     >>!   obliged to provide the source code for proprietary components     !<<\r
17     >>!   outside of the FreeRTOS kernel.                                   !<<\r
18     ***************************************************************************\r
19 \r
20     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
21     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
22     FOR A PARTICULAR PURPOSE.  Full license text is available on the following\r
23     link: http://www.freertos.org/a00114.html\r
24 \r
25     ***************************************************************************\r
26      *                                                                       *\r
27      *    FreeRTOS provides completely free yet professionally developed,    *\r
28      *    robust, strictly quality controlled, supported, and cross          *\r
29      *    platform software that is more than just the market leader, it     *\r
30      *    is the industry's de facto standard.                               *\r
31      *                                                                       *\r
32      *    Help yourself get started quickly while simultaneously helping     *\r
33      *    to support the FreeRTOS project by purchasing a FreeRTOS           *\r
34      *    tutorial book, reference manual, or both:                          *\r
35      *    http://www.FreeRTOS.org/Documentation                              *\r
36      *                                                                       *\r
37     ***************************************************************************\r
38 \r
39     http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading\r
40     the FAQ page "My application does not run, what could be wrong?".  Have you\r
41     defined configASSERT()?\r
42 \r
43     http://www.FreeRTOS.org/support - In return for receiving this top quality\r
44     embedded software for free we request you assist our global community by\r
45     participating in the support forum.\r
46 \r
47     http://www.FreeRTOS.org/training - Investing in training allows your team to\r
48     be as productive as possible as early as possible.  Now you can receive\r
49     FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
50     Ltd, and the world's leading authority on the world's leading RTOS.\r
51 \r
52     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
53     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
54     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
55 \r
56     http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
57     Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
58 \r
59     http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
60     Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
61     licenses offer ticketed support, indemnification and commercial middleware.\r
62 \r
63     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
64     engineered and independently SIL3 certified version for use in safety and\r
65     mission critical applications that require provable dependability.\r
66 \r
67     1 tab == 4 spaces!\r
68 */\r
69 \r
70 /*\r
71         BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER FOR UART1.\r
72 */\r
73 \r
74 /* Library includes. */\r
75 #include "91x_lib.h"\r
76 \r
77 /* Scheduler includes. */\r
78 #include "FreeRTOS.h"\r
79 #include "queue.h"\r
80 #include "semphr.h"\r
81 \r
82 /* Demo application includes. */\r
83 #include "serial.h"\r
84 /*-----------------------------------------------------------*/\r
85 \r
86 /* Misc defines. */\r
87 #define serINVALID_QUEUE                                ( ( QueueHandle_t ) 0 )\r
88 #define serNO_BLOCK                                             ( ( TickType_t ) 0 )\r
89 #define serTX_BLOCK_TIME                                ( 40 / portTICK_PERIOD_MS )\r
90 \r
91 /* Interrupt and status bit definitions. */\r
92 #define mainTXRIS 0x20  \r
93 #define mainRXRIS 0x50\r
94 #define serTX_FIFO_FULL 0x20\r
95 #define serCLEAR_ALL_INTERRUPTS 0x3ff\r
96 /*-----------------------------------------------------------*/\r
97 \r
98 /* The queue used to hold received characters. */\r
99 static QueueHandle_t xRxedChars;\r
100 \r
101 /* The semaphore used to wake a task waiting for space to become available\r
102 in the FIFO. */\r
103 static SemaphoreHandle_t xTxFIFOSemaphore;\r
104 \r
105 /*-----------------------------------------------------------*/\r
106 \r
107 /* UART interrupt handler. */\r
108 void UART1_IRQHandler( void );\r
109 \r
110 /* The interrupt service routine - called from the assembly entry point. */\r
111 __arm void UART1_IRQHandler( void );\r
112 \r
113 /*-----------------------------------------------------------*/\r
114 \r
115 /* Flag to indicate whether or not a task is blocked waiting for space on\r
116 the FIFO. */\r
117 static long lTaskWaiting = pdFALSE;\r
118 \r
119 /*\r
120  * See the serial2.h header file.\r
121  */\r
122 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )\r
123 {\r
124 xComPortHandle xReturn;\r
125 UART_InitTypeDef xUART1_Init;\r
126 GPIO_InitTypeDef GPIO_InitStructure;\r
127         \r
128         /* Create the queues used to hold Rx characters. */\r
129         xRxedChars = xQueueCreate( uxQueueLength, ( unsigned portBASE_TYPE ) sizeof( signed char ) );\r
130         \r
131         /* Create the semaphore used to wake a task waiting for space to become\r
132         available in the FIFO. */\r
133         vSemaphoreCreateBinary( xTxFIFOSemaphore );\r
134 \r
135         /* If the queue/semaphore was created correctly then setup the serial port\r
136         hardware. */\r
137         if( ( xRxedChars != serINVALID_QUEUE ) && ( xTxFIFOSemaphore != serINVALID_QUEUE ) )\r
138         {\r
139                 /* Pre take the semaphore so a task will block if it tries to access\r
140                 it. */\r
141                 xSemaphoreTake( xTxFIFOSemaphore, 0 );\r
142                 \r
143                 /* Configure the UART. */\r
144                 xUART1_Init.UART_WordLength = UART_WordLength_8D;\r
145                 xUART1_Init.UART_StopBits = UART_StopBits_1;\r
146                 xUART1_Init.UART_Parity = UART_Parity_No;\r
147                 xUART1_Init.UART_BaudRate = ulWantedBaud;\r
148                 xUART1_Init.UART_HardwareFlowControl = UART_HardwareFlowControl_None;\r
149                 xUART1_Init.UART_Mode = UART_Mode_Tx_Rx;\r
150                 xUART1_Init.UART_FIFO = UART_FIFO_Enable;\r
151 \r
152                 /* Enable the UART1 Clock */\r
153                 SCU_APBPeriphClockConfig( __UART1, ENABLE );\r
154                 \r
155                 /* Enable the GPIO3 Clock */\r
156                 SCU_APBPeriphClockConfig( __GPIO3, ENABLE );\r
157                 \r
158                 /* Configure UART1_Rx pin GPIO3.2 */\r
159                 GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;\r
160                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;\r
161                 GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;\r
162                 GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;\r
163                 GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1 ;\r
164                 GPIO_Init( GPIO3, &GPIO_InitStructure );\r
165                 \r
166                 /* Configure UART1_Tx pin GPIO3.3 */\r
167                 GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;\r
168                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;\r
169                 GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;\r
170                 GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;\r
171                 GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2 ;\r
172                 GPIO_Init( GPIO3, &GPIO_InitStructure );\r
173                 \r
174                 \r
175                 portENTER_CRITICAL();\r
176                 {               \r
177                         /* Configure the UART itself. */\r
178                         UART_DeInit( UART1 );           \r
179                         UART_Init( UART1, &xUART1_Init );\r
180                         UART_ITConfig( UART1, UART_IT_Receive | UART_IT_Transmit, ENABLE );\r
181                         UART1->ICR = serCLEAR_ALL_INTERRUPTS;\r
182                         UART_LoopBackConfig( UART1, DISABLE );\r
183                         UART_IrDACmd( IrDA1, DISABLE );\r
184 \r
185                         /* Configure the VIC for the UART interrupts. */                        \r
186                         VIC_Config( UART1_ITLine, VIC_IRQ, 9 );\r
187                         VIC_ITCmd( UART1_ITLine, ENABLE );\r
188 \r
189                         UART_Cmd( UART1, ENABLE );                      \r
190                         lTaskWaiting = pdFALSE;\r
191                 }\r
192                 portEXIT_CRITICAL();\r
193         }\r
194         else\r
195         {\r
196                 xReturn = ( xComPortHandle ) 0;\r
197         }\r
198 \r
199         /* This demo file only supports a single port but we have to return\r
200         something to comply with the standard demo header file. */\r
201         return xReturn;\r
202 }\r
203 /*-----------------------------------------------------------*/\r
204 \r
205 signed portBASE_TYPE xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )\r
206 {\r
207         /* The port handle is not required as this driver only supports one port. */\r
208         ( void ) pxPort;\r
209 \r
210         /* Get the next character from the buffer.  Return false if no characters\r
211         are available, or arrive before xBlockTime expires. */\r
212         if( xQueueReceive( xRxedChars, pcRxedChar, xBlockTime ) )\r
213         {\r
214                 return pdTRUE;\r
215         }\r
216         else\r
217         {\r
218                 return pdFALSE;\r
219         }\r
220 }\r
221 /*-----------------------------------------------------------*/\r
222 \r
223 void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )\r
224 {\r
225 signed char *pxNext;\r
226 \r
227         /* A couple of parameters that this port does not use. */\r
228         ( void ) usStringLength;\r
229         ( void ) pxPort;\r
230 \r
231         /* NOTE: This implementation does not handle the queue being full as no\r
232         block time is used! */\r
233 \r
234         /* The port handle is not required as this driver only supports UART1. */\r
235         ( void ) pxPort;\r
236 \r
237         /* Send each character in the string, one at a time. */\r
238         pxNext = ( signed char * ) pcString;\r
239         while( *pxNext )\r
240         {\r
241                 xSerialPutChar( pxPort, *pxNext, serNO_BLOCK );\r
242                 pxNext++;\r
243         }\r
244 }\r
245 /*-----------------------------------------------------------*/\r
246 \r
247 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )\r
248 {\r
249 portBASE_TYPE xReturn;\r
250 \r
251         portENTER_CRITICAL();\r
252         {\r
253                 /* Can we write to the FIFO? */\r
254                 if( UART1->FR & serTX_FIFO_FULL )\r
255                 {\r
256                         /* Wait for the interrupt letting us know there is space on the\r
257                         FIFO.  It is ok to block in a critical section, interrupts will be\r
258                         enabled for other tasks once we force a switch. */\r
259                         lTaskWaiting = pdTRUE;\r
260                         \r
261                         /* Just to be a bit different this driver uses a semaphore to\r
262                         block the sending task when the FIFO is full.  The standard COMTest\r
263                         task assumes a queue of adequate length exists so does not use\r
264                         a block time.  For this demo the block time is therefore hard\r
265                         coded. */\r
266                         xReturn = xSemaphoreTake( xTxFIFOSemaphore, serTX_BLOCK_TIME );\r
267                         if( xReturn )\r
268                         {\r
269                                 UART1->DR = cOutChar;\r
270                         }\r
271                 }\r
272                 else\r
273                 {\r
274                         UART1->DR = cOutChar;\r
275                         xReturn = pdPASS;\r
276                 }\r
277         }\r
278         portEXIT_CRITICAL();\r
279 \r
280         return xReturn;\r
281 }\r
282 /*-----------------------------------------------------------*/\r
283 \r
284 void vSerialClose( xComPortHandle xPort )\r
285 {\r
286         /* Not supported as not required by the demo application. */\r
287 }\r
288 /*-----------------------------------------------------------*/\r
289 \r
290 void UART1_IRQHandler( void )\r
291 {\r
292 signed char cChar;\r
293 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
294 \r
295         while( UART1->RIS &     mainRXRIS )\r
296         {\r
297                 /* The interrupt was caused by a character being received.  Grab the\r
298                 character from the DR and place it in the queue of received\r
299                 characters. */\r
300                 cChar = UART1->DR;\r
301                 xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );\r
302         }       \r
303         \r
304         if( UART1->RIS & mainTXRIS )\r
305         {\r
306                 if( lTaskWaiting == pdTRUE )\r
307                 {\r
308                         /* This interrupt was caused by space becoming available on the Tx\r
309                         FIFO, wake any task that is waiting to post (if any). */\r
310                         xSemaphoreGiveFromISR( xTxFIFOSemaphore, &xHigherPriorityTaskWoken );\r
311                         lTaskWaiting = pdFALSE;\r
312                 }\r
313                 \r
314                 UART1->ICR = mainTXRIS;\r
315         }\r
316 \r
317         /* If a task was woken by either a character being received or a character\r
318         being transmitted then we may need to switch to another task. */\r
319         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
320 }\r
321 \r
322 \r
323 \r
324 \r
325 \r
326         \r