Files
TI_C2000_F28377S_FreeRTOS/freertos_driverlib_f28377s/main.c
T
2026-09-05 09:19:49 -07:00

306 lines
9.4 KiB
C

// 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"
#define LED_R 41U // Red LED
#define LED_B 58U // Blue LED
#define SCI_RXDA_PIN 85U
#define SCI_TXDA_PIN 84U
// --------------------------------------------------------------------
#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);
// --------------------------------------------------------------------
// 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(LED_R, GPIO_PIN_TYPE_STD);
GPIO_setDirectionMode(LED_R, GPIO_DIR_MODE_OUT);
GPIO_writePin(LED_R, 0);
GPIO_setPadConfig(LED_B, GPIO_PIN_TYPE_STD);
GPIO_setDirectionMode(LED_B, GPIO_DIR_MODE_OUT);
GPIO_writePin(LED_B, 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);
// ------------------------------- FreeRTOS -------------------------------
xSemaphore = xSemaphoreCreateBinary();
if(xSemaphore == NULL) {
while(1);
}
// Create tasks dynamically
if(xTaskCreate(LED_TaskRed,
(const char *) "Red LED Task",
256,
NULL,
tskIDLE_PRIORITY + 2,
NULL) != pdPASS) {
ESTOP0;
}
if(xTaskCreate(LED_TaskBlue,
(const char *) "Blue LED Task",
256,
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) {
int uart_count = 0;
while(1) {
if(xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
// Toggle red LED
GPIO_togglePin(LED_R);
uart_count++;
printf("Hello from FreeRTOS running on the F28377S Coreboard, %d!\r\n", uart_count);
}
}
}
// 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(LED_B);
vTaskDelay(500);
}
}
// -----------------------------------------------------------------------------------------
// 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) {
// SCIA RX: GPIO85
GPIO_setMasterCore(SCI_RXDA_PIN, GPIO_CORE_CPU1);
GPIO_setPinConfig(GPIO_85_SCIRXDA);
GPIO_setDirectionMode(SCI_RXDA_PIN, GPIO_DIR_MODE_IN);
GPIO_setPadConfig(SCI_RXDA_PIN, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(SCI_RXDA_PIN, GPIO_QUAL_ASYNC);
// SCIA TX: GPIO84
GPIO_setMasterCore(SCI_TXDA_PIN, GPIO_CORE_CPU1);
GPIO_setPinConfig(GPIO_84_SCITXDA);
GPIO_setDirectionMode(SCI_TXDA_PIN, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(SCI_TXDA_PIN, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(SCI_TXDA_PIN, GPIO_QUAL_ASYNC);
// Configure SCIA
SCI_performSoftwareReset(SCIA_BASE);
SCI_setConfig(SCIA_BASE,
DEVICE_LSPCLK_FREQ,
115200U,
SCI_CONFIG_WLEN_8 |
SCI_CONFIG_STOP_ONE |
SCI_CONFIG_PAR_NONE);
SCI_resetChannels(SCIA_BASE);
SCI_resetRxFIFO(SCIA_BASE);
SCI_resetTxFIFO(SCIA_BASE);
// Recommended when using FIFO
SCI_clearInterruptStatus(SCIA_BASE, SCI_INT_TXFF | SCI_INT_RXFF);
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);
}
// -----------------------------------------------------------------------------------------