2 FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd.
\r
4 ***************************************************************************
\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
13 * then take a look at the FreeRTOS eBook *
\r
15 * "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
\r
16 * http://www.FreeRTOS.org/Documentation *
\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
23 ***************************************************************************
\r
25 This file is part of the FreeRTOS distribution.
\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
44 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
47 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
50 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
51 licensing and training services.
\r
55 INTERRUPT DRIVEN SERIAL PORT DRIVER.
\r
59 /******************************************************************************
\r
60 *** NOTE: COM0 == USART1, COM1 == USART2
\r
61 ******************************************************************************/
\r
64 /* Scheduler includes. */
\r
65 #include "FreeRTOS.h"
\r
69 /* Driver includes. */
\r
70 #include "CircularBuffer.h"
\r
72 /* Library includes. */
\r
73 #include "stm32f10x_lib.h"
\r
74 #include "stm32f10x_rcc.h"
\r
76 /* Driver includes. */
\r
77 #include "STM32_USART.h"
\r
78 /*-----------------------------------------------------------*/
\r
80 /* The number of COM ports that can be controlled at the same time. */
\r
81 #define serNUM_COM_PORTS ( 2 )
\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
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
91 #define serSEMAPHORE_MAX_COUNT ( 100 )
\r
93 /*-----------------------------------------------------------*/
\r
95 /* An Rx and a Tx buffer structure for each COM port. */
\r
96 static xCircularBuffer xCOMBufferDefinitions[ serNUM_COM_PORTS ][ 2 ];
\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
104 /* Semaphores used to block tasks that are waiting for characters to be
\r
106 static xSemaphoreHandle xCOM0RxSemaphore, xCOM1RxSemaphore;
\r
108 /*-----------------------------------------------------------*/
\r
110 /* UART interrupt handler. */
\r
111 void vUARTInterruptHandler( void );
\r
113 /*-----------------------------------------------------------*/
\r
116 * See serial.h in this project for parameter descriptions.
\r
118 long lCOMPortInit( unsigned long ulPort, unsigned long ulWantedBaud )
\r
120 long lReturn = pdFAIL;
\r
121 USART_InitTypeDef USART_InitStructure;
\r
122 NVIC_InitTypeDef NVIC_InitStructure;
\r
123 GPIO_InitTypeDef GPIO_InitStructure;
\r
125 if( ulPort < serNUM_COM_PORTS )
\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
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
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
148 vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serRX_BUFFER_INDEX ] ),
\r
150 configCOM0_RX_BUFFER_LENGTH,
\r
151 sizeof( unsigned char ),
\r
155 vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serTX_BUFFER_INDEX ] ),
\r
157 configCOM0_TX_BUFFER_LENGTH,
\r
158 sizeof( unsigned char ),
\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
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
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
177 USART_Init( USART1, &USART_InitStructure );
\r
178 USART_ITConfig( USART1, USART_IT_RXNE, ENABLE );
\r
180 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQChannel;
\r
181 NVIC_Init( &NVIC_InitStructure );
\r
183 USART_DMACmd( USART1, ( USART_DMAReq_Tx | USART_DMAReq_Rx ), ENABLE );
\r
184 USART_Cmd( USART1, ENABLE );
\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
192 vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serRX_BUFFER_INDEX ] ),
\r
194 configCOM1_RX_BUFFER_LENGTH,
\r
195 sizeof( unsigned char ),
\r
199 vInitialiseCircularBuffer( &( xCOMBufferDefinitions[ ulPort ][ serTX_BUFFER_INDEX ] ),
\r
201 configCOM1_TX_BUFFER_LENGTH,
\r
202 sizeof( unsigned char ),
\r
206 /* Enable COM0 clock - the ST libraries start numbering from 1. */
\r
207 RCC_APB2PeriphClockCmd( RCC_APB1Periph_USART2 | RCC_APB2Periph_GPIOA, ENABLE );
\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
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
220 USART_Init( USART2, &USART_InitStructure );
\r
221 USART_ITConfig( USART2, USART_IT_RXNE, ENABLE );
\r
223 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQChannel;
\r
224 NVIC_Init( &NVIC_InitStructure );
\r
226 USART_DMACmd( USART2, ( USART_DMAReq_Tx | USART_DMAReq_Rx ), ENABLE );
\r
227 USART_Cmd( USART2, ENABLE );
\r
230 /* Everything is ok. */
\r
236 /*-----------------------------------------------------------*/
\r
238 signed long xUSARTGetChar( long lPort, signed char *pcRxedChar, portTickType xBlockTime )
\r
242 /*-----------------------------------------------------------*/
\r
244 void vSerialPutString( long lPort, const signed char * const pcString, unsigned portSHORT usStringLength )
\r
247 /*-----------------------------------------------------------*/
\r
249 signed long xSerialPutChar( long lPort, signed char cOutChar, portTickType xBlockTime )
\r
253 /*-----------------------------------------------------------*/
\r
255 void vUARTInterruptHandler( void )
\r
257 long xHigherPriorityTaskWoken = pdFALSE;
\r
260 if( USART_GetITStatus( USART1, USART_IT_TXE ) == SET )
\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
266 /* A character was retrieved from the queue so can be sent to the
\r
268 USART_SendData( USART1, cChar );
\r
272 USART_ITConfig( USART1, USART_IT_TXE, DISABLE );
\r
276 if( USART_GetITStatus( USART1, USART_IT_RXNE ) == SET )
\r
278 cChar = USART_ReceiveData( USART1 );
\r
279 // xQueueSendFromISR( xRxedChars, &cChar, &xHigherPriorityTaskWoken );
\r
282 portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
\r