]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/STM32_USART.c
5a2832a1535b31a81719b8d6cec30bb3608095c5
[freertos] / Demo / CORTEX_STM32F103_GCC_Rowley / Drivers / STM32_USART.c
1 /*\r
2     FreeRTOS V7.0.0 - Copyright (C) 2011 Real Time Engineers Ltd.\r
3         \r
4 \r
5     ***************************************************************************\r
6      *                                                                       *\r
7      *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
8      *    Complete, revised, and edited pdf reference manuals are also       *\r
9      *    available.                                                         *\r
10      *                                                                       *\r
11      *    Purchasing FreeRTOS documentation will not only help you, by       *\r
12      *    ensuring you get running as quickly as possible and with an        *\r
13      *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
14      *    the FreeRTOS project to continue with its mission of providing     *\r
15      *    professional grade, cross platform, de facto standard solutions    *\r
16      *    for microcontrollers - completely free of charge!                  *\r
17      *                                                                       *\r
18      *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
19      *                                                                       *\r
20      *    Thank you for using FreeRTOS, and thank you for your support!      *\r
21      *                                                                       *\r
22     ***************************************************************************\r
23 \r
24 \r
25     This file is part of the FreeRTOS distribution.\r
26 \r
27     FreeRTOS is free software; you can redistribute it and/or modify it under\r
28     the terms of the GNU General Public License (version 2) as published by the\r
29     Free Software Foundation AND MODIFIED BY the FreeRTOS exception.\r
30     >>>NOTE<<< The modification to the GPL is included to allow you to\r
31     distribute a combined work that includes FreeRTOS without being obliged to\r
32     provide the source code for proprietary components outside of the FreeRTOS\r
33     kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
34     WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
35     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
36     more details. You should have received a copy of the GNU General Public\r
37     License and the FreeRTOS license exception along with FreeRTOS; if not it\r
38     can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
39     by writing to Richard Barry, contact details for whom are available on the\r
40     FreeRTOS WEB site.\r
41 \r
42     1 tab == 4 spaces!\r
43 \r
44     http://www.FreeRTOS.org - Documentation, latest information, license and\r
45     contact details.\r
46 \r
47     http://www.SafeRTOS.com - A version that is certified for use in safety\r
48     critical systems.\r
49 \r
50     http://www.OpenRTOS.com - Commercial support, development, porting,\r
51     licensing and training services.\r
52 */\r
53 \r
54 /*\r
55         INTERRUPT DRIVEN SERIAL PORT DRIVER.\r
56 */\r
57 \r
58 \r
59 /******************************************************************************\r
60 *** NOTE:  COM0 == USART1, COM1 == USART2\r
61 ******************************************************************************/\r
62 \r
63 \r
64 /* Scheduler includes. */\r
65 #include "FreeRTOS.h"\r
66 #include "task.h"\r
67 #include "queue.h"\r
68 #include "semphr.h"\r
69 \r
70 /* Library includes. */\r
71 #include "stm32f10x_lib.h"\r
72 \r
73 /* Driver includes. */\r
74 #include "STM32_USART.h"\r
75 /*-----------------------------------------------------------*/\r
76 \r
77 /* The number of COM ports that can be controlled at the same time. */\r
78 #define serNUM_COM_PORTS                                ( 2 )\r
79 \r
80 /* Queues are used to hold characters that are waiting to be transmitted.  This\r
81 constant sets the maximum number of characters that can be contained in such a\r
82 queue at any one time. */\r
83 #define serTX_QUEUE_LEN                                 ( 100 )\r
84 \r
85 /* Queues are used to hold characters that have been received but not yet \r
86 processed.  This constant sets the maximum number of characters that can be \r
87 contained in such a queue. */\r
88 #define serRX_QUEUE_LEN                                 ( 100 )\r
89 \r
90 /* The maximum amount of time that calls to lSerialPutString() should wait for\r
91 there to be space to post each character to the queue of characters waiting\r
92 transmission.  NOTE!  This is the time to wait per character - not the time to\r
93 wait for the entire string. */\r
94 #define serPUT_STRING_CHAR_DELAY                ( 5 / portTICK_RATE_MS )\r
95 \r
96 /*-----------------------------------------------------------*/\r
97 \r
98 /* References to the USART peripheral addresses themselves. */\r
99 static USART_TypeDef * const xUARTS[ serNUM_COM_PORTS ] = { ( ( USART_TypeDef * ) USART1_BASE ), ( ( USART_TypeDef * ) USART2_BASE ) };\r
100 \r
101 /* Queues used to hold characters waiting to be transmitted - one queue per port. */\r
102 static xQueueHandle xCharsForTx[ serNUM_COM_PORTS ] = { 0 };\r
103 \r
104 /* Queues holding received characters - one queue per port. */\r
105 static xQueueHandle xRxedChars[ serNUM_COM_PORTS ] = { 0 };\r
106 \r
107 /*-----------------------------------------------------------*/\r
108 \r
109 /* UART interrupt handlers, as named in the vector table. */\r
110 void USART1_IRQHandler( void );\r
111 void USART2_IRQHandler( void );\r
112 \r
113 /*-----------------------------------------------------------*/\r
114 \r
115 /*\r
116  * See header file for parameter descriptions.\r
117  */\r
118 long lCOMPortInit( unsigned long ulPort, unsigned long ulWantedBaud )\r
119 {\r
120 long lReturn = pdFAIL;\r
121 USART_InitTypeDef USART_InitStructure;\r
122 NVIC_InitTypeDef NVIC_InitStructure;\r
123 GPIO_InitTypeDef GPIO_InitStructure;\r
124 \r
125         if( ulPort < serNUM_COM_PORTS )\r
126         {\r
127                 /* The common (not port dependent) part of the initialisation. */\r
128                 USART_InitStructure.USART_BaudRate = ulWantedBaud;\r
129                 USART_InitStructure.USART_WordLength = USART_WordLength_8b;\r
130                 USART_InitStructure.USART_StopBits = USART_StopBits_1;\r
131                 USART_InitStructure.USART_Parity = USART_Parity_No;\r
132                 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;\r
133                 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;\r
134                 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY;\r
135                 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;\r
136                 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;\r
137 \r
138 \r
139                 /* Init the buffer structures with the buffer for the COM port being\r
140                 initialised, and perform any non-common initialisation necessary.  This\r
141                 does not check to see if the COM port has already been initialised. */\r
142                 if( ulPort == 0 )\r
143                 {\r
144                         /* Create the queue of chars that are waiting to be sent to COM0. */\r
145                         xCharsForTx[ 0 ] = xQueueCreate( serTX_QUEUE_LEN, sizeof( char ) );\r
146 \r
147                         /* Create the queue used to hold characters received from COM0. */\r
148                         xRxedChars[ 0 ] = xQueueCreate( serRX_QUEUE_LEN, sizeof( char ) );\r
149 \r
150                         /* Enable COM0 clock - the ST libraries start numbering from UART1. */\r
151                         RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE ); \r
152 \r
153                         /* Configure USART1 Rx (PA10) as input floating */\r
154                         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;\r
155                         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;\r
156                         GPIO_Init( GPIOA, &GPIO_InitStructure );\r
157                         \r
158                         /* Configure USART1 Tx (PA9) as alternate function push-pull */\r
159                         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;\r
160                         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;\r
161                         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;\r
162                         GPIO_Init( GPIOA, &GPIO_InitStructure );\r
163 \r
164                         USART_Init( USART1, &USART_InitStructure );             \r
165                         USART_ITConfig( USART1, USART_IT_RXNE, ENABLE );\r
166                         \r
167                         NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;\r
168                         NVIC_Init( &NVIC_InitStructure );\r
169                         \r
170             USART_DMACmd( USART1, ( USART_DMAReq_Tx | USART_DMAReq_Rx ), ENABLE );\r
171                         USART_Cmd( USART1, ENABLE );    \r
172 \r
173                         /* Everything is ok. */\r
174                         lReturn = pdPASS;\r
175                 }\r
176                 else if( ulPort == 1 )\r
177                 {\r
178                         /* Create the queue of chars that are waiting to be sent to COM1. */\r
179                         xCharsForTx[ 1 ] = xQueueCreate( serTX_QUEUE_LEN, sizeof( char ) );\r
180 \r
181                         /* Create the queue used to hold characters received from COM0. */\r
182                         xRxedChars[ 1 ] = xQueueCreate( serRX_QUEUE_LEN, sizeof( char ) );\r
183 \r
184                         /* Enable COM0 clock - the ST libraries start numbering from 1. */\r
185                         RCC_APB2PeriphClockCmd( RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOA, ENABLE ); \r
186 \r
187                         /* Configure USART2 Rx (PA3) as input floating */\r
188                         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;\r
189                         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;\r
190                         GPIO_Init( GPIOA, &GPIO_InitStructure );\r
191                         \r
192                         /* Configure USART2 Tx (PA2) as alternate function push-pull */\r
193                         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;\r
194                         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;\r
195                         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;\r
196                         GPIO_Init( GPIOA, &GPIO_InitStructure );\r
197 \r
198                         USART_Init( USART2, &USART_InitStructure );             \r
199                         USART_ITConfig( USART2, USART_IT_RXNE, ENABLE );\r
200                         \r
201                         NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQChannel;\r
202                         NVIC_Init( &NVIC_InitStructure );\r
203                         \r
204             USART_DMACmd( USART2, ( USART_DMAReq_Tx | USART_DMAReq_Rx ), ENABLE );\r
205                         USART_Cmd( USART2, ENABLE );    \r
206 \r
207                         /* Everything is ok. */\r
208                         lReturn = pdPASS;\r
209                 }       \r
210                 else\r
211                 {\r
212                         /* Nothing to do unless more than two ports are supported. */\r
213                 }\r
214         }\r
215         \r
216         return lReturn;\r
217 }\r
218 /*-----------------------------------------------------------*/\r
219 \r
220 signed long xSerialGetChar( long lPort, signed char *pcRxedChar, portTickType xBlockTime )\r
221 {\r
222 long lReturn = pdFAIL;\r
223 \r
224         if( lPort < serNUM_COM_PORTS ) \r
225         {\r
226                 if( xQueueReceive( xRxedChars[ lPort ], pcRxedChar, xBlockTime ) == pdPASS )\r
227                 {\r
228                         lReturn = pdPASS;\r
229                 }\r
230         }\r
231 \r
232         return lReturn;\r
233 }\r
234 /*-----------------------------------------------------------*/\r
235 \r
236 long lSerialPutString( long lPort, const char * const pcString, unsigned long ulStringLength )\r
237 {\r
238 long lReturn;\r
239 unsigned long ul;\r
240 \r
241         if( lPort < serNUM_COM_PORTS )\r
242         {\r
243                 lReturn = pdPASS;\r
244 \r
245                 for( ul = 0; ul < ulStringLength; ul++ )\r
246                 {\r
247                         if( xQueueSend( xCharsForTx[ lPort ], &( pcString[ ul ] ), serPUT_STRING_CHAR_DELAY ) != pdPASS )\r
248                         {\r
249                                 /* Cannot fit any more in the queue.  Try turning the Tx on to \r
250                                 clear some space. */\r
251                                 USART_ITConfig( xUARTS[ lPort ], USART_IT_TXE, ENABLE );\r
252                                 vTaskDelay( serPUT_STRING_CHAR_DELAY );\r
253 \r
254                                 /* Go back and try again. */\r
255                                 continue;\r
256                         }\r
257                 }\r
258 \r
259         USART_ITConfig( xUARTS[ lPort ], USART_IT_TXE, ENABLE );\r
260         }\r
261         else\r
262         {\r
263                 lReturn = pdFAIL;\r
264         }\r
265 \r
266         return lReturn;\r
267 }\r
268 /*-----------------------------------------------------------*/\r
269 \r
270 signed long xSerialPutChar( long lPort, signed char cOutChar, portTickType xBlockTime )\r
271 {\r
272 long lReturn;\r
273 \r
274         if( xQueueSend( xCharsForTx[ lPort ], &cOutChar, xBlockTime ) == pdPASS )\r
275         {\r
276                 lReturn = pdPASS;\r
277                 USART_ITConfig( xUARTS[ lPort ], USART_IT_TXE, ENABLE );\r
278         }\r
279         else\r
280         {\r
281                 lReturn = pdFAIL;\r
282         }\r
283 \r
284         return lReturn;\r
285 }\r
286 /*-----------------------------------------------------------*/\r
287 \r
288 void USART1_IRQHandler( void )\r
289 {\r
290 long xHigherPriorityTaskWoken = pdFALSE;\r
291 char cChar;\r
292 \r
293         if( USART_GetITStatus( USART1, USART_IT_TXE ) == SET )\r
294         {\r
295                 /* The interrupt was caused by the THR becoming empty.  Are there any\r
296                 more characters to transmit? */\r
297                 if( xQueueReceiveFromISR( xCharsForTx[ 0 ], &cChar, &xHigherPriorityTaskWoken ) )\r
298                 {\r
299                         /* A character was retrieved from the buffer so can be sent to the\r
300                         THR now. */\r
301                         USART_SendData( USART1, cChar );\r
302                 }\r
303                 else\r
304                 {\r
305                         USART_ITConfig( USART1, USART_IT_TXE, DISABLE );                \r
306                 }               \r
307         }\r
308         \r
309         if( USART_GetITStatus( USART1, USART_IT_RXNE ) == SET )\r
310         {\r
311                 cChar = USART_ReceiveData( USART1 );\r
312                 xQueueSendFromISR( xRxedChars[ 0 ], &cChar, &xHigherPriorityTaskWoken );\r
313         }       \r
314         \r
315         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
316 }\r
317 /*-----------------------------------------------------------*/\r
318 \r
319 void USART2_IRQHandler( void )\r
320 {\r
321 }\r
322 \r
323 \r
324 \r
325 \r
326         \r