--- /dev/null
+/*\r
+ FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd.\r
+ All rights reserved\r
+\r
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify it under\r
+ the terms of the GNU General Public License (version 2) as published by the\r
+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
+\r
+ ***************************************************************************\r
+ >>! NOTE: The modification to the GPL is included to allow you to !<<\r
+ >>! distribute a combined work that includes FreeRTOS without being !<<\r
+ >>! obliged to provide the source code for proprietary components !<<\r
+ >>! outside of the FreeRTOS kernel. !<<\r
+ ***************************************************************************\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following\r
+ link: http://www.freertos.org/a00114.html\r
+\r
+ ***************************************************************************\r
+ * *\r
+ * FreeRTOS provides completely free yet professionally developed, *\r
+ * robust, strictly quality controlled, supported, and cross *\r
+ * platform software that is more than just the market leader, it *\r
+ * is the industry's de facto standard. *\r
+ * *\r
+ * Help yourself get started quickly while simultaneously helping *\r
+ * to support the FreeRTOS project by purchasing a FreeRTOS *\r
+ * tutorial book, reference manual, or both: *\r
+ * http://www.FreeRTOS.org/Documentation *\r
+ * *\r
+ ***************************************************************************\r
+\r
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading\r
+ the FAQ page "My application does not run, what could be wrong?". Have you\r
+ defined configASSERT()?\r
+\r
+ http://www.FreeRTOS.org/support - In return for receiving this top quality\r
+ embedded software for free we request you assist our global community by\r
+ participating in the support forum.\r
+\r
+ http://www.FreeRTOS.org/training - Investing in training allows your team to\r
+ be as productive as possible as early as possible. Now you can receive\r
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers\r
+ Ltd, and the world's leading authority on the world's leading RTOS.\r
+\r
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
+\r
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.\r
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.\r
+\r
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High\r
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS\r
+ licenses offer ticketed support, indemnification and commercial middleware.\r
+\r
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
+ engineered and independently SIL3 certified version for use in safety and\r
+ mission critical applications that require provable dependability.\r
+\r
+ 1 tab == 4 spaces!\r
+*/\r
+\r
+/*\r
+ BASIC INTERRUPT DRIVEN SERIAL PORT DRIVER.\r
+\r
+ Note1: This driver is used specifically to provide an interface to the\r
+ FreeRTOS+CLI command interpreter. It is *not* intended to be a generic\r
+ serial port driver. Nor is it intended to be used as an example of an\r
+ efficient implementation. In particular, a queue is used to buffer\r
+ received characters, which is fine in this case as key presses arrive\r
+ slowly, but a DMA and/or RAM buffer should be used in place of the queue in\r
+ applications that expect higher throughput.\r
+\r
+ Note2: This driver does not attempt to handle UART errors.\r
+*/\r
+\r
+/* Scheduler includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "queue.h"\r
+#include "semphr.h"\r
+\r
+/* Demo application includes. */\r
+#include "serial.h"\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * The UART interrupt handler.\r
+ */\r
+void vUART_Handler( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The queue into which received key presses are placed. NOTE THE COMMENTS AT\r
+THE TOP OF THIS FILE REGARDING THE USE OF QUEUES FOR THIS PURPOSE. */\r
+static QueueHandle_t xRxQueue = NULL;\r
+\r
+/* Variables used in the Tx interrupt to send a string. */\r
+static volatile const signed char *pcStringStart = NULL, *pcStringEnd = NULL;\r
+static volatile TaskHandle_t xTransmittingTask = NULL;\r
+\r
+static EUSCI_A0_Type * const pxUARTA0 = ( EUSCI_A0_Type * ) EUSCI_A0_MODULE;\r
+\r
+/* UART Configuration for 19200 baud. Value generated using the tool provided\r
+on the following page:\r
+http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430BaudRateConverter/index.html\r
+ */\r
+const eUSCI_UART_Config xUARTConfig =\r
+{\r
+ EUSCI_A_UART_CLOCKSOURCE_SMCLK, /* SMCLK Clock Source. */\r
+ 156, /* BRDIV */\r
+ 4, /* UCxBRF */\r
+ 0, /* UCxBRS */\r
+ EUSCI_A_UART_NO_PARITY, /* No Parity. */\r
+ EUSCI_A_UART_LSB_FIRST, /* MSB First. */\r
+ EUSCI_A_UART_ONE_STOP_BIT, /* One stop bit. */\r
+ EUSCI_A_UART_MODE, /* UART mode. */\r
+ EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION /* Low Frequency Mode. */\r
+};\r
+\r
+/*\r
+ * See the serial2.h header file.\r
+ */\r
+xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned long uxQueueLength )\r
+{\r
+ /* Create the queue used to hold received characters. NOTE THE COMMENTS AT\r
+ THE TOP OF THIS FILE REGARDING THE USE OF QUEUES FOR THIS PURPSOE. */\r
+ xRxQueue = xQueueCreate( uxQueueLength, sizeof( char ) );\r
+ configASSERT( xRxQueue );\r
+\r
+ /* Use the library functions to initialise and enable the UART. */\r
+ MAP_UART_initModule( EUSCI_A0_MODULE, &xUARTConfig );\r
+ MAP_UART_enableModule( EUSCI_A0_MODULE );\r
+ MAP_UART_clearInterruptFlag( EUSCI_A0_MODULE, EUSCI_A_UART_RECEIVE_INTERRUPT | EUSCI_A_UART_TRANSMIT_INTERRUPT );\r
+ MAP_UART_enableInterrupt( EUSCI_A0_MODULE, EUSCI_A_UART_RECEIVE_INTERRUPT );\r
+\r
+ /* The interrupt handler uses the FreeRTOS API function so its priority must\r
+ be at or below the configured maximum system call interrupt priority.\r
+ configKERNEL_INTERRUPT_PRIORITY is the priority used by the RTOS tick and\r
+ (should) always be set to the minimum priority. */\r
+ MAP_Interrupt_setPriority( INT_EUSCIA0, configKERNEL_INTERRUPT_PRIORITY );\r
+ MAP_Interrupt_enableInterrupt( INT_EUSCIA0 );\r
+\r
+ /* Only one UART is supported so the handle is not used. */\r
+ return ( xComPortHandle ) 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t xSerialGetChar( xComPortHandle pxPort, signed char *pcRxedChar, TickType_t xBlockTime )\r
+{\r
+BaseType_t xReturn;\r
+\r
+ /* Only a single port is supported. */\r
+ ( void ) pxPort;\r
+\r
+ /* Obtain a received character from the queue - entering the Blocked state\r
+ (so not consuming any processing time) to wait for a character if one is not\r
+ already available. */\r
+ xReturn = xQueueReceive( xRxQueue, pcRxedChar, xBlockTime );\r
+ return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )\r
+{\r
+const TickType_t xMaxWaitTime = pdMS_TO_TICKS( 20UL * ( uint32_t ) usStringLength );\r
+\r
+ /* Only a single port is supported. */\r
+ ( void ) pxPort;\r
+\r
+ /* Note there is no mutual exclusion at the driver level. If more than one\r
+ task is using the serial port then mutual exclusion should be provided where\r
+ this function is called. */\r
+\r
+ /* Ensure notifications are not already waiting. */\r
+ ( void ) ulTaskNotifyTake( pdTRUE, 0 );\r
+\r
+ /* Remember which task is sending the byte. */\r
+ xTransmittingTask = xTaskGetCurrentTaskHandle();\r
+\r
+ /* Mark the start and end of the data being sent. */\r
+ pcStringStart = pcString;\r
+ pcStringEnd = pcStringStart + usStringLength;\r
+\r
+ /* Start to send the first byte. */\r
+ pxUARTA0->rTXBUF.r = ( uint_fast8_t ) *pcString;\r
+\r
+ /* Enable the interrupt then wait for the byte to be sent. The interrupt\r
+ will be disabled again in the ISR. */\r
+ MAP_UART_enableInterrupt( EUSCI_A0_MODULE, EUSCI_A_UART_TRANSMIT_INTERRUPT );\r
+ ulTaskNotifyTake( pdTRUE, xMaxWaitTime );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )\r
+{\r
+const TickType_t xMaxWaitTime = pdMS_TO_TICKS( 20UL );\r
+\r
+ /* Only a single port is supported. */\r
+ ( void ) pxPort;\r
+\r
+ /* Note there is no mutual exclusion at the driver level. If more than one\r
+ task is using the serial port then mutual exclusion should be provided where\r
+ this function is called. */\r
+\r
+ /* Ensure notifications are not already waiting. */\r
+ ( void ) ulTaskNotifyTake( pdTRUE, 0 );\r
+\r
+ /* Remember which task is sending the byte. */\r
+ xTransmittingTask = xTaskGetCurrentTaskHandle();\r
+\r
+ /* Mark the start and end of the data being sent - in this case just a\r
+ single byte. */\r
+ pcStringStart = &cOutChar;\r
+ pcStringEnd = pcStringStart + sizeof( cOutChar );\r
+\r
+ /* Start to send the byte. */\r
+ pxUARTA0->rTXBUF.r = ( uint_fast8_t ) cOutChar;\r
+\r
+ /* Enable the interrupt then wait for the byte to be sent. The interrupt\r
+ will be disabled again in the ISR. */\r
+ MAP_UART_enableInterrupt( EUSCI_A0_MODULE, EUSCI_A_UART_TRANSMIT_INTERRUPT );\r
+ ulTaskNotifyTake( pdTRUE, xMaxWaitTime );\r
+\r
+ return pdPASS;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vSerialClose(xComPortHandle xPort)\r
+{\r
+ /* Not supported as not required by the demo application. */\r
+ ( void ) xPort;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vUART_Handler( void )\r
+{\r
+uint8_t ucChar;\r
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+uint_fast8_t xInterruptStatus;\r
+\r
+ xInterruptStatus = MAP_UART_getEnabledInterruptStatus( EUSCI_A0_MODULE );\r
+\r
+ if( ( xInterruptStatus & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG ) != 0x00 )\r
+ {\r
+ /* Obtain the character. */\r
+ ucChar = MAP_UART_receiveData( EUSCI_A0_MODULE );\r
+\r
+ /* Send the character to the queue. Note the comments at the top of this\r
+ file with regards to the inefficiency of this method for anything other than\r
+ very low bandwidth communications.\r
+\r
+ If writing to the queue unblocks a task, and the unblocked task has a\r
+ priority above the currently running task (the task that this interrupt\r
+ interrupted), then xHigherPriorityTaskWoken will be set to pdTRUE inside the\r
+ xQueueSendFromISR() function. xHigherPriorityTaskWoken is then passed to\r
+ portYIELD_FROM_ISR() at the end of this interrupt handler to request a\r
+ context switch so the interrupt returns directly to the (higher priority)\r
+ unblocked task. */\r
+ xQueueSendFromISR( xRxQueue, &ucChar, &xHigherPriorityTaskWoken );\r
+ }\r
+\r
+ if( ( xInterruptStatus & EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG ) != 0x00 )\r
+ {\r
+ /* Are there more characters to transmit? */\r
+ pcStringStart++;\r
+ if( ( uint32_t ) pcStringStart < ( uint32_t ) pcStringEnd )\r
+ {\r
+ /* This is probably quite a heavy wait function just for writing to\r
+ the Tx register. An optimised design would probably replace this\r
+ with a simple register write. */\r
+ pxUARTA0->rTXBUF.r = ( uint_fast8_t ) *pcStringStart;\r
+ }\r
+ else\r
+ {\r
+ /* No more characters to send. Disable the interrupt and notify the\r
+ task, if the task is waiting. */\r
+ MAP_UART_disableInterrupt( EUSCI_A0_MODULE, EUSCI_A_UART_TRANSMIT_INTERRUPT );\r
+ if( xTransmittingTask != NULL )\r
+ {\r
+ vTaskNotifyGiveFromISR( xTransmittingTask, &xHigherPriorityTaskWoken );\r
+ xTransmittingTask = NULL;\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ /* portYIELD_FROM_ISR() will request a context switch if executing this\r
+ interrupt handler caused a task to leave the blocked state, and the task\r
+ that left the blocked state has a higher priority than the currently running\r
+ task (the task this interrupt interrupted). See the comment above the calls\r
+ to xSemaphoreGiveFromISR() and xQueueSendFromISR() within this function. */\r
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+}\r
+\r
+\r
+\r
+\r
+\r