//############################################################################# // // For running the application open the COM port with the following settings // using a terminal: // - Find correct COM port // - Bits per second = 9600 // - Data Bits = 8 // - Parity = None // - Stop Bits = 1 // - Hardware Control = None // The program will print out the test results on COM port // //############################################################################# // Standard includes #include #include #include #include #include // Driverlib headers #include "driverlib.h" #include "device.h" // FreeRTOS headers #include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include "queue.h" #include "timers.h" // STDOUT redirection specific #include "uart_drv.h" #include "sci.h" // -------------------------------------------------------------------- #if defined (__TI_EABI__) void *malloc(size_t xSize); #pragma WEAK (malloc) #endif #if defined (__TI_EABI__) // malloc - Traps malloc calls void *malloc(size_t xSize) { (void)xSize; // There should not be a heap defined, trap any attempts to call malloc() taskDISABLE_INTERRUPTS(); for(;;) { ESTOP0; // Optional: useful during CCS debug } } #endif #if(configAPPLICATION_ALLOCATED_HEAP == 1) uint8_t ucHeap[configTOTAL_HEAP_SIZE]; #pragma DATA_SECTION(ucHeap, ".freertosHeap") #pragma DATA_ALIGN(ucHeap, portBYTE_ALIGNMENT) #endif // UART stdout redirection configuration related functions void UartSetup(void); void UartPutChar(uint16_t charToWrite); extern int checkPrintf(void); // -------------------------------------------------------------------- // Configuration of CPU timer 1 void configCPUTimer(uint32_t cpuTimer, uint32_t period_us); __interrupt void timer1_ISR(void); void LED_TaskRed(void * pvParameters); void LED_TaskBlue(void * pvParameters); static SemaphoreHandle_t xSemaphore = NULL; void main(void) { // Initializes device clock and peripherals Device_init(); // Initializes PIE and clears PIE registers. Disables CPU interrupts Interrupt_initModule(); // --------------------------- Initializes GPIO --------------------------- Device_initGPIO(); GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD); GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT); GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0); GPIO_setPadConfig(DEVICE_GPIO_PIN_LED2, GPIO_PIN_TYPE_STD); GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED2, GPIO_DIR_MODE_OUT); GPIO_writePin(DEVICE_GPIO_PIN_LED2, 0); // ------------------------------------------------------------------------ // Clear all interrupts and initialize PIE vector table // Disable CPU interrupts DINT; // Disable CPU interrupts and clear all CPU interrupt flags IER = 0x0000; IFR = 0x0000; // Initializes the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR) Interrupt_initVectorTable(); // ------------------------- Configure CPU Timer -------------------------- // ISR functions found within this project Interrupt_register(INT_TIMER1, &timer1_ISR); // Configure CPU timer 1 to interrupt every given period: 1000000 us configCPUTimer(CPUTIMER1_BASE, 1000000); CPUTimer_clearOverflowFlag(CPUTIMER1_BASE); // Enable CPU timer 1 interrupt and start CPU timer 1 Interrupt_enable(INT_TIMER1); CPUTimer_startTimer(CPUTIMER1_BASE); // ------------------------------------------------------------------------ // Enable global Interrupts and higher priority real-time debug events EINT; // Enable Global interrupt INTM ERTM; // Enable Global real-time interrupt DBGM // ------------------------ Redirect STDOUT to SCI ------------------------ //************************************************************************** // NOTE: SCI Configuration for this example is done in UartSetup() // As an alternative, the user can configure SCI here in the main, and then // provide an empty UartSetup() function. UartSetup() must be defined, even // if it is empty. //************************************************************************** // Add the UART device. When fopen is called with a filename that // begins "uart:", the UART device will be used to handle the file add_device("uart", _SSA, UART_open, UART_close, UART_read, UART_write, UART_lseek, UART_unlink, UART_rename); // Assign stdout to be a UART device assert(freopen("uart:", "w", stdout) != NULL); // printf() tests checkPrintf(); // Ptr string = Hello world! // printf test // (null) is null pointer // 5 = 5 // 129 = - max int // char a = 'a' // hex ff = ff // hex 00 = 00 // signed -3 = unsigned 65533 = hex fffd // 0 message(s) // 0 message(s) with % // justif: "left " // justif: " right" // 3: 0003 zero padded // 3: 3 left justif. // 3: 3 right justif. // -3: -003 zero padded // -3: -3 left justif. // -3: -3 right justif. // ------------------------------- FreeRTOS ------------------------------- xSemaphore = xSemaphoreCreateBinary(); if(xSemaphore == NULL) { while(1); } // Create tasks dynamically if(xTaskCreate(LED_TaskRed, (const char *) "Red LED Task", 128, NULL, tskIDLE_PRIORITY + 2, NULL) != pdPASS) { ESTOP0; } if(xTaskCreate(LED_TaskBlue, (const char *) "Blue LED Task", 128, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS) { ESTOP0; } // Start the scheduler. This should not return vTaskStartScheduler(); } // ----------------------------------------------------------------------------------------- // This is an event-driven task. It sits in a blocked state waiting for // xSemaphore to be available by calling xSemaphoreTake() with a timeout // of portMAX_DELAY. Because Timer 1 releases this semaphore every 100 ms, // the Red LED task will unblock and toggle the LED exactly every 100 ms. // It is created with a higher priority of tskIDLE_PRIORITY + 2. void LED_TaskRed(void * pvParameters) { while(1) { if(xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) { // Toggle red LED GPIO_togglePin(DEVICE_GPIO_PIN_LED1); } } } // This is a time-driven task. It simply toggles the blue LED and then puts // itself to sleep using vTaskDelay(500 / portTICK_PERIOD_MS). // Based on the RTOS configuration, this creates a 500 ms delay cycle. // It runs at a lower priority of tskIDLE_PRIORITY + 1. void LED_TaskBlue(void * pvParameters) { while(1) { // Toggle blue LED GPIO_togglePin(DEVICE_GPIO_PIN_LED2); vTaskDelay(500 / portTICK_PERIOD_MS); } } // ----------------------------------------------------------------------------------------- // configCPUTimer - This function initializes the selected timer to the // period specified by the "freq" and "period" variables. The "freq" is // CPU frequency in Hz and the period in uSeconds. The timer is held in // the stopped state after configuration. void configCPUTimer(uint32_t cpuTimer, uint32_t period_us) { uint32_t periodCount, freq = DEVICE_SYSCLK_FREQ; // Initialize timer period periodCount = ((freq / 1000000) * period_us); CPUTimer_setPeriod(cpuTimer, periodCount); // Set pre-scale counter to divide by 1 (SYSCLKOUT) CPUTimer_setPreScaler(cpuTimer, 0); // Initializes timer control register. The timer is stopped, // reloaded, free run disabled, and interrupt enabled. // Additionally, the free and soft bits are set CPUTimer_stopTimer(cpuTimer); CPUTimer_reloadTimerCounter(cpuTimer); CPUTimer_setEmulationMode( cpuTimer, CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT ); CPUTimer_enableInterrupt(cpuTimer); } // When Timer 1 fires, the Interrupt Service Routine executes // xSemaphoreGiveFromISR(). This unlocks the semaphore so a waiting task // can proceed. portYIELD_FROM_ISR() is then called to force an immediate // FreeRTOS context switch if the newly unblocked task has a higher priority // than the interrupted task. __interrupt void timer1_ISR(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; if(xSemaphore != NULL) { xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } CPUTimer_clearOverflowFlag(CPUTIMER1_BASE); } // ----------------------------------------------------------------------------------------- // UartSetup - Configures SCIA void UartSetup(void) { // DEVICE_GPIO_PIN_SCIRXDA is the SCI Rx pin GPIO_setMasterCore(DEVICE_GPIO_PIN_SCIRXDA, GPIO_CORE_CPU1); GPIO_setPinConfig(DEVICE_GPIO_CFG_SCIRXDA); GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCIRXDA, GPIO_DIR_MODE_IN); GPIO_setPadConfig(DEVICE_GPIO_PIN_SCIRXDA, GPIO_PIN_TYPE_STD); GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCIRXDA, GPIO_QUAL_ASYNC); // DEVICE_GPIO_PIN_SCITXDA is the SCI Tx pin GPIO_setMasterCore(DEVICE_GPIO_PIN_SCITXDA, GPIO_CORE_CPU1); GPIO_setPinConfig(DEVICE_GPIO_CFG_SCITXDA); GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCITXDA, GPIO_DIR_MODE_OUT); GPIO_setPadConfig(DEVICE_GPIO_PIN_SCITXDA, GPIO_PIN_TYPE_STD); GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCITXDA, GPIO_QUAL_ASYNC); // Initialize SCIA and its FIFO SCI_performSoftwareReset(SCIA_BASE); // Configure SCIA with FIFO SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 9600, (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE)); SCI_resetChannels(SCIA_BASE); SCI_resetRxFIFO(SCIA_BASE); SCI_resetTxFIFO(SCIA_BASE); SCI_enableFIFO(SCIA_BASE); SCI_enableModule(SCIA_BASE); SCI_performSoftwareReset(SCIA_BASE); } // UartPutChar - Implements SCI based putchar() void UartPutChar(uint16_t charToWrite) { SCI_writeCharBlockingFIFO(SCIA_BASE, charToWrite); } // -----------------------------------------------------------------------------------------