]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_STM32F103_GCC_Rowley/Drivers/STM32_USART.c
Work in progress - checked in for backup only.
[freertos] / Demo / CORTEX_STM32F103_GCC_Rowley / Drivers / STM32_USART.c
1 /*\r
2     FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.\r
3 \r
4     ***************************************************************************\r
5     *                                                                         *\r
6     * If you are:                                                             *\r
7     *                                                                         *\r
8     *    + New to FreeRTOS,                                                   *\r
9     *    + Wanting to learn FreeRTOS or multitasking in general quickly       *\r
10     *    + Looking for basic training,                                        *\r
11     *    + Wanting to improve your FreeRTOS skills and productivity           *\r
12     *                                                                         *\r
13     * then take a look at the FreeRTOS eBook                                  *\r
14     *                                                                         *\r
15     *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *\r
16     *                  http://www.FreeRTOS.org/Documentation                  *\r
17     *                                                                         *\r
18     * A pdf reference manual is also available.  Both are usually delivered   *\r
19     * to your inbox within 20 minutes to two hours when purchased between 8am *\r
20     * and 8pm GMT (although please allow up to 24 hours in case of            *\r
21     * exceptional circumstances).  Thank you for your support!                *\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 exception to the GPL is included to allow you to distribute\r
31     a combined work that includes FreeRTOS without being obliged to provide the\r
32     source code for proprietary components outside of the FreeRTOS kernel.\r
33     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT\r
34     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\r
35     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 "queue.h"\r
67 #include "semphr.h"\r
68 \r
69 /* Driver includes. */\r
70 #include "CircularBuffer.h"\r
71 \r
72 /* Library includes. */\r
73 #include "stm32f10x_lib.h"\r
74 #include "stm32f10x_rcc.h"\r
75 \r
76 /* Driver includes. */\r
77 #include "STM32_USART.h"\r
78 /*-----------------------------------------------------------*/\r
79 \r
80 /* The number of COM ports that can be controlled at the same time. */\r
81 #define serNUM_COM_PORTS                                ( 2 )\r
82 \r
83 /* Indexes into the xCOMBufferDefinitions array for the Rx and Tx buffers. */\r
84 #define serRX_BUFFER_INDEX                              ( 0 )\r
85 #define serTX_BUFFER_INDEX                              ( 1 )\r
86 \r
87 /* A counting semaphore is used to allows tasks to block to wait for characters\r
88 to be received.  This constant defines the max count.  Making this value higher\r
89 does not change the amount of RAM used by the semaphore, so its worth making it\r
90 quite high. */\r
91 #define serSEMAPHORE_MAX_COUNT                  ( 100 )\r
92 \r
93 /*-----------------------------------------------------------*/\r
94 \r
95 /* An Rx and a Tx buffer structure for each COM port. */\r
96 static xCircularBuffer xCOMBufferDefinitions[ serNUM_COM_PORTS ][ 2 ];\r
97 \r
98 /* The buffers themselves. */\r
99 static unsigned char ucCOM0_Rx_Buffer[ configCOM0_RX_BUFFER_LENGTH ];\r
100 static unsigned char ucCOM0_Tx_Buffer[ configCOM0_TX_BUFFER_LENGTH ];\r
101 static unsigned char ucCOM1_Rx_Buffer[ configCOM1_RX_BUFFER_LENGTH ];\r
102 static unsigned char ucCOM1_Tx_Buffer[ configCOM1_TX_BUFFER_LENGTH ];\r
103 \r
104 /* Semaphores used to block tasks that are waiting for characters to be\r
105 received. */\r
106 static xSemaphoreHandle xCOM0RxSemaphore, xCOM1RxSemaphore;\r
107 \r
108 /*-----------------------------------------------------------*/\r
109 \r
110 /* UART interrupt handler. */\r
111 void vUARTInterruptHandler( void );\r
112 \r
113 /*-----------------------------------------------------------*/\r
114 \r
115 /*\r
116  * See serial.h in this project 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 semaphore used to enable tasks to block to wait for\r
145                         characters to be received. */\r
146             xCOM0RxSemaphore = xSemaphoreCreateCounting( serSEMAPHORE_MAX_COUNT, 0 );\r
147 \r
148                         vInitialiseCircularBuffer(      &( xCOMBufferDefinitions[ ulPort ][ serRX_BUFFER_INDEX ] ),\r
149                                                                                 ucCOM0_Rx_Buffer,\r
150                                                                                 configCOM0_RX_BUFFER_LENGTH,\r
151                                                                                 sizeof( unsigned char ),\r
152                                                                                 NULL\r
153                                                                         );\r
154 \r
155                         vInitialiseCircularBuffer(      &( xCOMBufferDefinitions[ ulPort ][ serTX_BUFFER_INDEX ] ),\r
156                                                                                 ucCOM0_Tx_Buffer,\r
157                                                                                 configCOM0_TX_BUFFER_LENGTH,\r
158                                                                                 sizeof( unsigned char ),\r
159                                                                                 NULL\r
160                                                                         );\r
161 \r
162                         /* Enable COM1 clock - the ST libraries start numbering from UART1, \r
163                         making this UART 2. */\r
164                         RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE ); \r
165 \r
166                         /* Configure USART1 Rx (PA10) as input floating */\r
167                         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;\r
168                         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;\r
169                         GPIO_Init( GPIOA, &GPIO_InitStructure );\r
170                         \r
171                         /* Configure USART1 Tx (PA9) as alternate function push-pull */\r
172                         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;\r
173                         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;\r
174                         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;\r
175                         GPIO_Init( GPIOA, &GPIO_InitStructure );\r
176 \r
177                         USART_Init( USART1, &USART_InitStructure );             \r
178                         USART_ITConfig( USART1, USART_IT_RXNE, ENABLE );\r
179                         \r
180                         NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;\r
181                         NVIC_Init( &NVIC_InitStructure );\r
182                         \r
183             USART_DMACmd( USART1, ( USART_DMAReq_Tx | USART_DMAReq_Rx ), ENABLE );\r
184                         USART_Cmd( USART1, ENABLE );    \r
185                 }\r
186                 else\r
187                 {\r
188                         /* Create the semaphore used to enable tasks to block to wait for\r
189                         characters to be received. */\r
190             xCOM1RxSemaphore = xSemaphoreCreateCounting( serSEMAPHORE_MAX_COUNT, 0 );\r
191 \r
192                         vInitialiseCircularBuffer(      &( xCOMBufferDefinitions[ ulPort ][ serRX_BUFFER_INDEX ] ),\r
193                                                                                 ucCOM1_Rx_Buffer,\r
194                                                                                 configCOM1_RX_BUFFER_LENGTH,\r
195                                                                                 sizeof( unsigned char ),\r
196                                                                                 NULL\r
197                                                                         );\r
198 \r
199                         vInitialiseCircularBuffer(      &( xCOMBufferDefinitions[ ulPort ][ serTX_BUFFER_INDEX ] ),\r
200                                                                                 ucCOM1_Tx_Buffer,\r
201                                                                                 configCOM1_TX_BUFFER_LENGTH,\r
202                                                                                 sizeof( unsigned char ),\r
203                                                                                 NULL\r
204                                                                         );\r
205 \r
206                         /* Enable COM0 clock - the ST libraries start numbering from 1. */\r
207                         RCC_APB2PeriphClockCmd( RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOA, ENABLE ); \r
208 \r
209                         /* Configure USART2 Rx (PA3) as input floating */\r
210                         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;\r
211                         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;\r
212                         GPIO_Init( GPIOA, &GPIO_InitStructure );\r
213                         \r
214                         /* Configure USART2 Tx (PA2) as alternate function push-pull */\r
215                         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;\r
216                         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;\r
217                         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;\r
218                         GPIO_Init( GPIOA, &GPIO_InitStructure );\r
219 \r
220                         USART_Init( USART2, &USART_InitStructure );             \r
221                         USART_ITConfig( USART2, USART_IT_RXNE, ENABLE );\r
222                         \r
223                         NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQChannel;\r
224                         NVIC_Init( &NVIC_InitStructure );\r
225                         \r
226             USART_DMACmd( USART2, ( USART_DMAReq_Tx | USART_DMAReq_Rx ), ENABLE );\r
227                         USART_Cmd( USART2, ENABLE );    \r
228                 }       \r
229                         \r
230                 /* Everything is ok. */\r
231                 lReturn = pdPASS;\r
232         }\r
233         \r
234         return lReturn;\r
235 }\r
236 /*-----------------------------------------------------------*/\r
237 \r
238 signed long xUSARTGetChar( long lPort, signed char *pcRxedChar, portTickType xBlockTime )\r
239 {\r
240         return pdFALSE;\r
241 }\r
242 /*-----------------------------------------------------------*/\r
243 \r
244 void vSerialPutString( long lPort, const signed char * const pcString, unsigned portSHORT usStringLength )\r
245 {\r
246 }\r
247 /*-----------------------------------------------------------*/\r
248 \r
249 signed long xSerialPutChar( long lPort, signed char cOutChar, portTickType xBlockTime )\r
250 {\r
251         return pdFALSE;\r
252 }\r
253 /*-----------------------------------------------------------*/\r
254 \r
255 void vUARTInterruptHandler( void )\r
256 {\r
257 long xHigherPriorityTaskWoken = pdFALSE;\r
258 char cChar;\r
259 \r
260         if( USART_GetITStatus( USART1, USART_IT_TXE ) == SET )\r
261         {\r
262                 /* The interrupt was caused by the THR becoming empty.  Are there any\r
263                 more characters to transmit? */\r
264 if( 0 )//               if( xQueueReceiveFromISR( xCharsForTx, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )\r
265                 {\r
266                         /* A character was retrieved from the queue so can be sent to the\r
267                         THR now. */\r
268                         USART_SendData( USART1, cChar );\r
269                 }\r
270                 else\r
271                 {\r
272                         USART_ITConfig( USART1, USART_IT_TXE, DISABLE );                \r
273                 }               \r
274         }\r
275         \r
276         if( USART_GetITStatus( USART1, USART_IT_RXNE ) == SET )\r
277         {\r
278                 cChar = USART_ReceiveData( USART1 );\r
279 //              xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );\r
280         }       \r
281         \r
282         portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );\r
283 }\r
284 \r
285 \r
286 \r
287 \r
288 \r
289         \r