]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M4F_MSP432_LaunchPad_IAR_CCS_Keil/Full_Demo/serial.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M4F_MSP432_LaunchPad_IAR_CCS_Keil / Full_Demo / serial.c
1 /*\r
2     FreeRTOS V8.2.1 - Copyright (C) 2015 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.\r
72 \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
80 \r
81         Note2:  This driver does not attempt to handle UART errors.\r
82 */\r
83 \r
84 /* Scheduler includes. */\r
85 #include "FreeRTOS.h"\r
86 #include "task.h"\r
87 #include "queue.h"\r
88 #include "semphr.h"\r
89 \r
90 /* Demo application includes. */\r
91 #include "serial.h"\r
92 \r
93 /*-----------------------------------------------------------*/\r
94 \r
95 /*\r
96  * The UART interrupt handler.\r
97  */\r
98 void vUART_Handler( void );\r
99 \r
100 /*-----------------------------------------------------------*/\r
101 \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
105 \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
109 \r
110 static EUSCI_A0_Type * const pxUARTA0 = ( EUSCI_A0_Type * ) EUSCI_A0_MODULE;\r
111 \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
115  */\r
116 const eUSCI_UART_Config xUARTConfig =\r
117 {\r
118         EUSCI_A_UART_CLOCKSOURCE_SMCLK, /* SMCLK Clock Source. */\r
119         156,                                                    /* BRDIV */\r
120         4,                                                              /* UCxBRF */\r
121         0,                                                              /* UCxBRS */\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
127 };\r
128 \r
129 /*\r
130  * See the serial2.h header file.\r
131  */\r
132 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned long uxQueueLength )\r
133 {\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
138 \r
139         /* Use the library functions to initialise and enable the UART. */\r
140         MAP_UART_initModule( EUSCI_A0_MODULE, &xUARTConfig );\r
141         MAP_UART_enableModule( EUSCI_A0_MODULE );\r
142         MAP_UART_clearInterruptFlag( EUSCI_A0_MODULE, EUSCI_A_UART_RECEIVE_INTERRUPT | EUSCI_A_UART_TRANSMIT_INTERRUPT );\r
143         MAP_UART_enableInterrupt( EUSCI_A0_MODULE, EUSCI_A_UART_RECEIVE_INTERRUPT );\r
144 \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
151 \r
152         /* Only one UART is supported so the handle is not used. */\r
153         return ( xComPortHandle ) 0;\r
154 }\r
155 /*-----------------------------------------------------------*/\r
156 \r
157 BaseType_t xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )\r
158 {\r
159 BaseType_t xReturn;\r
160 \r
161         /* Only a single port is supported. */\r
162         ( void ) pxPort;\r
163 \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
168         return xReturn;\r
169 }\r
170 /*-----------------------------------------------------------*/\r
171 \r
172 void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )\r
173 {\r
174 const TickType_t xMaxWaitTime = pdMS_TO_TICKS( 20UL * ( uint32_t ) usStringLength );\r
175 \r
176         /* Only a single port is supported. */\r
177         ( void ) pxPort;\r
178 \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
182 \r
183         /* Ensure notifications are not already waiting. */\r
184         ( void ) ulTaskNotifyTake( pdTRUE, 0 );\r
185 \r
186         /* Remember which task is sending the byte. */\r
187         xTransmittingTask = xTaskGetCurrentTaskHandle();\r
188 \r
189         /* Mark the start and end of the data being sent. */\r
190         pcStringStart = pcString;\r
191         pcStringEnd = pcStringStart + usStringLength;\r
192 \r
193         /* Start to send the first byte. */\r
194         pxUARTA0->rTXBUF.r = ( uint_fast8_t ) *pcString;\r
195 \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_MODULE, EUSCI_A_UART_TRANSMIT_INTERRUPT );\r
199         ulTaskNotifyTake( pdTRUE, xMaxWaitTime );\r
200 }\r
201 /*-----------------------------------------------------------*/\r
202 \r
203 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )\r
204 {\r
205 const TickType_t xMaxWaitTime = pdMS_TO_TICKS( 20UL );\r
206 \r
207         /* Only a single port is supported. */\r
208         ( void ) pxPort;\r
209 \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
213 \r
214         /* Ensure notifications are not already waiting. */\r
215         ( void ) ulTaskNotifyTake( pdTRUE, 0 );\r
216 \r
217         /* Remember which task is sending the byte. */\r
218         xTransmittingTask = xTaskGetCurrentTaskHandle();\r
219 \r
220         /* Mark the start and end of the data being sent - in this case just a\r
221         single byte. */\r
222         pcStringStart = &cOutChar;\r
223         pcStringEnd = pcStringStart + sizeof( cOutChar );\r
224 \r
225         /* Start to send the byte. */\r
226         pxUARTA0->rTXBUF.r = ( uint_fast8_t ) cOutChar;\r
227 \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_MODULE, EUSCI_A_UART_TRANSMIT_INTERRUPT );\r
231         ulTaskNotifyTake( pdTRUE, xMaxWaitTime );\r
232 \r
233         return pdPASS;\r
234 }\r
235 /*-----------------------------------------------------------*/\r
236 \r
237 void vSerialClose(xComPortHandle xPort)\r
238 {\r
239         /* Not supported as not required by the demo application. */\r
240         ( void ) xPort;\r
241 }\r
242 /*-----------------------------------------------------------*/\r
243 \r
244 void vUART_Handler( void )\r
245 {\r
246 uint8_t ucChar;\r
247 BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
248 uint_fast8_t xInterruptStatus;\r
249 \r
250         xInterruptStatus = MAP_UART_getEnabledInterruptStatus( EUSCI_A0_MODULE );\r
251 \r
252         if( ( xInterruptStatus & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG ) != 0x00 )\r
253         {\r
254                 /* Obtain the character. */\r
255                 ucChar = MAP_UART_receiveData( EUSCI_A0_MODULE );\r
256 \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
260 \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
267                 unblocked task. */\r
268                 xQueueSendFromISR( xRxQueue, &ucChar, &xHigherPriorityTaskWoken );\r
269         }\r
270 \r
271         if( ( xInterruptStatus & EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG ) != 0x00 )\r
272         {\r
273                 /* Are there more characters to transmit? */\r
274                 pcStringStart++;\r
275                 if( ( uint32_t ) pcStringStart < ( uint32_t ) pcStringEnd )\r
276                 {\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->rTXBUF.r = ( uint_fast8_t ) *pcStringStart;\r
281                 }\r
282                 else\r
283                 {\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_MODULE, EUSCI_A_UART_TRANSMIT_INTERRUPT );\r
287                         if( xTransmittingTask != NULL )\r
288                         {\r
289                                 vTaskNotifyGiveFromISR( xTransmittingTask, &xHigherPriorityTaskWoken );\r
290                                 xTransmittingTask = NULL;\r
291                         }\r
292                 }\r
293         }\r
294 \r
295 \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
302 }\r
303 \r
304 \r
305 \r
306 \r
307 \r