2 FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 This file is part of the FreeRTOS distribution.
\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
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
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
25 ***************************************************************************
\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
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
37 ***************************************************************************
\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
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
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
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
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
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
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
71 BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER.
\r
73 Note1: This driver is used specifically to provide an interface to the
\r
74 FreeRTOS+CLI command interpreter. It is *not* intended to be a generic
\r
75 serial port driver. Nor is it intended to be used as an example of an
\r
76 efficient implementation. In particular, a queue is used to buffer
\r
77 received characters, which is fine in this case as key presses arrive
\r
78 slowly, but a DMA and/or RAM buffer should be used in place of the queue in
\r
79 applications that expect higher throughput.
\r
81 Note2: This driver does not attempt to handle UART errors.
\r
84 /* Scheduler includes. */
\r
85 #include "FreeRTOS.h"
\r
90 /* Demo application includes. */
\r
93 /*-----------------------------------------------------------*/
\r
96 * The UART interrupt handler.
\r
98 void vUART_Handler( void );
\r
100 /*-----------------------------------------------------------*/
\r
102 /* The queue into which received key presses are placed. NOTE THE COMMENTS AT
\r
103 THE TOP OF THIS FILE REGARDING THE USE OF QUEUES FOR THIS PURPOSE. */
\r
104 static QueueHandle_t xRxQueue = NULL;
\r
106 /* Variables used in the Tx interrupt to send a string. */
\r
107 static volatile const signed char *pcStringStart = NULL, *pcStringEnd = NULL;
\r
108 static volatile TaskHandle_t xTransmittingTask = NULL;
\r
110 static EUSCI_A_Type * const pxUARTA0 = ( EUSCI_A_Type * ) EUSCI_A0_BASE;
\r
112 /* UART Configuration for 19200 baud. Value generated using the tool provided
\r
113 on the following page:
\r
114 http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html
\r
116 const eUSCI_UART_Config xUARTConfig =
\r
118 EUSCI_A_UART_CLOCKSOURCE_SMCLK, /* SMCLK Clock Source. */
\r
122 EUSCI_A_UART_NO_PARITY, /* No Parity. */
\r
123 EUSCI_A_UART_LSB_FIRST, /* MSB First. */
\r
124 EUSCI_A_UART_ONE_STOP_BIT, /* One stop bit. */
\r
125 EUSCI_A_UART_MODE, /* UART mode. */
\r
126 EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION /* Low Frequency Mode. */
\r
130 * See the serial2.h header file.
\r
132 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned long uxQueueLength )
\r
134 /* Create the queue used to hold received characters. NOTE THE COMMENTS AT
\r
135 THE TOP OF THIS FILE REGARDING THE USE OF QUEUES FOR THIS PURPSOE. */
\r
136 xRxQueue = xQueueCreate( uxQueueLength, sizeof( char ) );
\r
137 configASSERT( xRxQueue );
\r
139 /* Use the library functions to initialise and enable the UART. */
\r
140 MAP_UART_initModule( EUSCI_A0_BASE, &xUARTConfig );
\r
141 MAP_UART_enableModule( EUSCI_A0_BASE );
\r
142 MAP_UART_clearInterruptFlag( EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT | EUSCI_A_UART_TRANSMIT_INTERRUPT );
\r
143 MAP_UART_enableInterrupt( EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT );
\r
145 /* The interrupt handler uses the FreeRTOS API function so its priority must
\r
146 be at or below the configured maximum system call interrupt priority.
\r
147 configKERNEL_INTERRUPT_PRIORITY is the priority used by the RTOS tick and
\r
148 (should) always be set to the minimum priority. */
\r
149 MAP_Interrupt_setPriority( INT_EUSCIA0, configKERNEL_INTERRUPT_PRIORITY );
\r
150 MAP_Interrupt_enableInterrupt( INT_EUSCIA0 );
\r
152 /* Only one UART is supported so the handle is not used. */
\r
153 return ( xComPortHandle ) 0;
\r
155 /*-----------------------------------------------------------*/
\r
157 BaseType_t xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )
\r
159 BaseType_t xReturn;
\r
161 /* Only a single port is supported. */
\r
164 /* Obtain a received character from the queue - entering the Blocked state
\r
165 (so not consuming any processing time) to wait for a character if one is not
\r
166 already available. */
\r
167 xReturn = xQueueReceive( xRxQueue, pcRxedChar, xBlockTime );
\r
170 /*-----------------------------------------------------------*/
\r
172 void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )
\r
174 const TickType_t xMaxWaitTime = pdMS_TO_TICKS( 20UL * ( uint32_t ) usStringLength );
\r
176 /* Only a single port is supported. */
\r
179 /* Note there is no mutual exclusion at the driver level. If more than one
\r
180 task is using the serial port then mutual exclusion should be provided where
\r
181 this function is called. */
\r
183 /* Ensure notifications are not already waiting. */
\r
184 ( void ) ulTaskNotifyTake( pdTRUE, 0 );
\r
186 /* Remember which task is sending the byte. */
\r
187 xTransmittingTask = xTaskGetCurrentTaskHandle();
\r
189 /* Mark the start and end of the data being sent. */
\r
190 pcStringStart = pcString;
\r
191 pcStringEnd = pcStringStart + usStringLength;
\r
193 /* Start to send the first byte. */
\r
194 pxUARTA0->TXBUF = ( uint_fast8_t ) *pcString;
\r
196 /* Enable the interrupt then wait for the byte to be sent. The interrupt
\r
197 will be disabled again in the ISR. */
\r
198 MAP_UART_enableInterrupt( EUSCI_A0_BASE, EUSCI_A_UART_TRANSMIT_INTERRUPT );
\r
199 ulTaskNotifyTake( pdTRUE, xMaxWaitTime );
\r
201 /*-----------------------------------------------------------*/
\r
203 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )
\r
205 const TickType_t xMaxWaitTime = pdMS_TO_TICKS( 20UL );
\r
207 /* Only a single port is supported. */
\r
210 /* Note there is no mutual exclusion at the driver level. If more than one
\r
211 task is using the serial port then mutual exclusion should be provided where
\r
212 this function is called. */
\r
214 /* Ensure notifications are not already waiting. */
\r
215 ( void ) ulTaskNotifyTake( pdTRUE, 0 );
\r
217 /* Remember which task is sending the byte. */
\r
218 xTransmittingTask = xTaskGetCurrentTaskHandle();
\r
220 /* Mark the start and end of the data being sent - in this case just a
\r
222 pcStringStart = &cOutChar;
\r
223 pcStringEnd = pcStringStart + sizeof( cOutChar );
\r
225 /* Start to send the byte. */
\r
226 pxUARTA0->TXBUF = ( uint_fast8_t ) cOutChar;
\r
228 /* Enable the interrupt then wait for the byte to be sent. The interrupt
\r
229 will be disabled again in the ISR. */
\r
230 MAP_UART_enableInterrupt( EUSCI_A0_BASE, EUSCI_A_UART_TRANSMIT_INTERRUPT );
\r
231 ulTaskNotifyTake( pdTRUE, xMaxWaitTime );
\r
235 /*-----------------------------------------------------------*/
\r
237 void vSerialClose(xComPortHandle xPort)
\r
239 /* Not supported as not required by the demo application. */
\r
242 /*-----------------------------------------------------------*/
\r
244 void vUART_Handler( void )
\r
247 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
248 uint_fast8_t xInterruptStatus;
\r
250 xInterruptStatus = MAP_UART_getEnabledInterruptStatus( EUSCI_A0_BASE );
\r
252 if( ( xInterruptStatus & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG ) != 0x00 )
\r
254 /* Obtain the character. */
\r
255 ucChar = MAP_UART_receiveData( EUSCI_A0_BASE );
\r
257 /* Send the character to the queue. Note the comments at the top of this
\r
258 file with regards to the inefficiency of this method for anything other than
\r
259 very low bandwidth communications.
\r
261 If writing to the queue unblocks a task, and the unblocked task has a
\r
262 priority above the currently running task (the task that this interrupt
\r
263 interrupted), then xHigherPriorityTaskWoken will be set to pdTRUE inside the
\r
264 xQueueSendFromISR() function. xHigherPriorityTaskWoken is then passed to
\r
265 portYIELD_FROM_ISR() at the end of this interrupt handler to request a
\r
266 context switch so the interrupt returns directly to the (higher priority)
\r
268 xQueueSendFromISR( xRxQueue, &ucChar, &xHigherPriorityTaskWoken );
\r
271 if( ( xInterruptStatus & EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG ) != 0x00 )
\r
273 /* Are there more characters to transmit? */
\r
275 if( ( uint32_t ) pcStringStart < ( uint32_t ) pcStringEnd )
\r
277 /* This is probably quite a heavy wait function just for writing to
\r
278 the Tx register. An optimised design would probably replace this
\r
279 with a simple register write. */
\r
280 pxUARTA0->TXBUF = ( uint_fast8_t ) *pcStringStart;
\r
284 /* No more characters to send. Disable the interrupt and notify the
\r
285 task, if the task is waiting. */
\r
286 MAP_UART_disableInterrupt( EUSCI_A0_BASE, EUSCI_A_UART_TRANSMIT_INTERRUPT );
\r
287 if( xTransmittingTask != NULL )
\r
289 vTaskNotifyGiveFromISR( xTransmittingTask, &xHigherPriorityTaskWoken );
\r
290 xTransmittingTask = NULL;
\r
296 /* portYIELD_FROM_ISR() will request a context switch if executing this
\r
297 interrupt handler caused a task to leave the blocked state, and the task
\r
298 that left the blocked state has a higher priority than the currently running
\r
299 task (the task this interrupt interrupted). See the comment above the calls
\r
300 to xSemaphoreGiveFromISR() and xQueueSendFromISR() within this function. */
\r
301 portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
\r