329 lines
10 KiB
C
329 lines
10 KiB
C
//#############################################################################
|
|
//
|
|
// 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <file.h>
|
|
#include <string.h>
|
|
|
|
// 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);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------
|
|
|