From ab8270867eca05cbe066b6fdb95baf86e3d84eda Mon Sep 17 00:00:00 2001 From: toddmorehouse Date: Sun, 19 May 2019 02:58:48 -0400 Subject: [PATCH] Added support for TM4C123 series. Fixed crashing issue. Had to add another parameter to task scheduler init (sysctl periph value). Did simple testing to prove task scheduler works. More advanced testing, like measuring jitter, was not done. --- .cproject | 86 ++++---- .launches/TIVA-Task-Scheduler.launch | 4 + TaskScheduler/TaskScheduler.c | 11 +- TaskScheduler/TaskScheduler.h | 4 +- main.c | 60 +++++- targetConfigs/Tiva TM4C123GH6PM.ccxml | 13 ++ tm4c123gh6pm.cmd | 45 ++++ tm4c123gh6pm_startup_ccs.c | 300 ++++++++++++++++++++++++++ 8 files changed, 467 insertions(+), 56 deletions(-) create mode 100644 targetConfigs/Tiva TM4C123GH6PM.ccxml create mode 100644 tm4c123gh6pm.cmd create mode 100644 tm4c123gh6pm_startup_ccs.c diff --git a/.cproject b/.cproject index 3531f71..80c0250 100644 --- a/.cproject +++ b/.cproject @@ -15,70 +15,73 @@ - - + + + @@ -119,6 +122,9 @@ + + + diff --git a/.launches/TIVA-Task-Scheduler.launch b/.launches/TIVA-Task-Scheduler.launch index 15a0020..fbc8274 100644 --- a/.launches/TIVA-Task-Scheduler.launch +++ b/.launches/TIVA-Task-Scheduler.launch @@ -1,9 +1,13 @@ + + + + diff --git a/TaskScheduler/TaskScheduler.c b/TaskScheduler/TaskScheduler.c index e75711d..4ced95f 100644 --- a/TaskScheduler/TaskScheduler.c +++ b/TaskScheduler/TaskScheduler.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #ifndef NULL #define NULL 0 @@ -48,19 +50,21 @@ void TaskSchedulerTimer_ISR(void){ TimerIntClear(scheduler.timerBase, TIMER_TIMA_TIMEOUT); } -void InitializeTaskScheduler(uint32_t timerBase, uint32_t sysClkFreq, uint32_t timerIntBase){ +void InitializeTaskScheduler(uint32_t timerBase, uint32_t sysCtlTimerPeriph, uint32_t sysClkFreq, uint32_t timerIntBase){ //Initialize the task scheduler scheduler.timerBase = timerBase; scheduler.pTaskListRoot = NULL; //Initialize the timer - SysCtlPeripheralEnable(timerBase); + SysCtlPeripheralEnable(sysCtlTimerPeriph); //Wait for the clock to stabilize - SysCtlDelay(10); + SysCtlDelay(100); + IntMasterEnable(); //Configure the timer to be a periodic 100us timer TimerConfigure(timerBase, TIMER_CFG_PERIODIC); + TimerLoadSet(timerBase, TIMER_A, sysClkFreq * TASK_SCHEDULER_TIMER_PERIOD / 1000000); //Configure the ISR @@ -70,7 +74,6 @@ void InitializeTaskScheduler(uint32_t timerBase, uint32_t sysClkFreq, uint32_t t //Enable the timer and interrupts TimerEnable(timerBase, TIMER_A); - IntMasterEnable(); } void AddTask(Task *pTask){ diff --git a/TaskScheduler/TaskScheduler.h b/TaskScheduler/TaskScheduler.h index 3968b48..189db52 100644 --- a/TaskScheduler/TaskScheduler.h +++ b/TaskScheduler/TaskScheduler.h @@ -6,7 +6,7 @@ //For the most accurate timer, choose a frequency that is an integer #define TASK_SCHEDULER_TIMER_PERIOD 100 //us -#define TASK_SCHEDULER_TICKS_IN_ONE_SECOND 1/TASK_SCHEDULER_TIMER_PERIOD +#define TASK_SCHEDULER_TICKS_IN_ONE_SECOND 1/TASK_SCHEDULER_TIMER_PERIOD * 1000000 struct Task_tag; typedef struct Task_tag Task; @@ -28,7 +28,7 @@ typedef struct TaskScheduler_tag{ Task *pTaskListRoot; } TaskScheduler; -void InitializeTaskScheduler(uint32_t timerBase, uint32_t sysClkFreq, uint32_t timerIntBase); +void InitializeTaskScheduler(uint32_t timerBase, uint32_t sysCtlTimerPeriph, uint32_t sysClkFreq, uint32_t timerIntBase); void AddTask(Task *pTask); void RemoveTask(Task *pTask); diff --git a/main.c b/main.c index 9b953cd..31afc71 100644 --- a/main.c +++ b/main.c @@ -19,9 +19,16 @@ #include "driverlib/ssi.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" +#include "driverlib/fpu.h" +#include +#include -//System clock running at 120MHz -#define SYS_CLK 120000000 +//System clock running at 120MHz if 129 or 80MHz if 123 +#ifdef PART_TM4C129 + #define SYS_CLK 120000000 +#elif PART_TM4C123 + #define SYS_CLK 80000000 +#endif void EnableClock(void); void EnablePeripherals(); @@ -34,18 +41,58 @@ void sprintfloat(char *Buffer, float val, int arg1){ sprintf(Buffer, "%i.%i", LeftSide, RightSide); } +void print(){ + UARTprintf("Task 1"); +} + +void print2(){ + UARTprintf("Task 2"); +} + +void print3(){ + UARTprintf("Task 3"); +} + +Task tasks[3]; + int main(void) { + FPULazyStackingEnable(); EnableClock(); EnablePeripherals(); + + InitializeTaskScheduler(TIMER0_BASE, SYSCTL_PERIPH_TIMER0, SYS_CLK, INT_TIMER0A); + + tasks[0].period = 3; + tasks[0].enabled = 1; + tasks[0].pCallback = print; + + tasks[1].period = 1.5; + tasks[1].enabled = 1; + tasks[1].pCallback = print2; + + tasks[2].period = 1; + tasks[2].enabled = 1; + tasks[2].pCallback = print3; + + AddTask(&tasks[0]); + AddTask(&tasks[1]); + AddTask(&tasks[2]); + + while(1){ + } } void EnableClock(void){ - +#ifdef PART_TM4C129 SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), SYS_CLK); +#elif PART_TM4C123 + SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); + uint32_t g_ui32SysClock = SysCtlClockGet (); +#endif } /* @@ -53,13 +100,6 @@ void EnableClock(void){ */ void EnablePeripherals(void){ InitConsole(); - - InitializeTaskScheduler(TIMER0_BASE, SYS_CLK, INT_TIMER0A); - - while(1){ - UARTprintf("Hello world!"); - SysCtlDelay(SYS_CLK / 3); - } } //Initializes UART0 to be used as a console. diff --git a/targetConfigs/Tiva TM4C123GH6PM.ccxml b/targetConfigs/Tiva TM4C123GH6PM.ccxml new file mode 100644 index 0000000..ec5b8f5 --- /dev/null +++ b/targetConfigs/Tiva TM4C123GH6PM.ccxml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/tm4c123gh6pm.cmd b/tm4c123gh6pm.cmd new file mode 100644 index 0000000..8f6aca9 --- /dev/null +++ b/tm4c123gh6pm.cmd @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * Default Linker Command file for the Texas Instruments TM4C123GH6PM + * + * This is derived from revision 15071 of the TivaWare Library. + * + *****************************************************************************/ + +--retain=g_pfnVectors + +MEMORY +{ + FLASH (RX) : origin = 0x00000000, length = 0x00040000 + SRAM (RWX) : origin = 0x20000000, length = 0x00008000 +} + +/* The following command line options are set as part of the CCS project. */ +/* If you are building using the command line, or for some reason want to */ +/* define them here, you can uncomment and modify these lines as needed. */ +/* If you are using CCS for building, it is probably better to make any such */ +/* modifications in your CCS project and leave this file alone. */ +/* */ +/* --heap_size=0 */ +/* --stack_size=256 */ +/* --library=rtsv7M4_T_le_eabi.lib */ + +/* Section allocation in memory */ + +SECTIONS +{ + .intvecs: > 0x00000000 + .text : > FLASH + .const : > FLASH + .cinit : > FLASH + .pinit : > FLASH + .init_array : > FLASH + + .vtable : > 0x20000000 + .data : > SRAM + .bss : > SRAM + .sysmem : > SRAM + .stack : > SRAM +} + +__STACK_TOP = __stack + 512; diff --git a/tm4c123gh6pm_startup_ccs.c b/tm4c123gh6pm_startup_ccs.c new file mode 100644 index 0000000..a8f43e7 --- /dev/null +++ b/tm4c123gh6pm_startup_ccs.c @@ -0,0 +1,300 @@ +//***************************************************************************** +// +// Startup code for use with TI's Code Composer Studio. +// +// Copyright (c) 2011-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +//***************************************************************************** + +#include + +//***************************************************************************** +// +// Forward declaration of the default fault handlers. +// +//***************************************************************************** +void ResetISR(void); +static void NmiSR(void); +static void FaultISR(void); +static void IntDefaultHandler(void); + +//***************************************************************************** +// +// External declaration for the reset handler that is to be called when the +// processor is started +// +//***************************************************************************** +extern void _c_int00(void); + +//***************************************************************************** +// +// Linker variable that marks the top of the stack. +// +//***************************************************************************** +extern uint32_t __STACK_TOP; + +//***************************************************************************** +// +// External declarations for the interrupt handlers used by the application. +// +//***************************************************************************** +// To be added by user + +//***************************************************************************** +// +// The vector table. Note that the proper constructs must be placed on this to +// ensure that it ends up at physical address 0x0000.0000 or at the start of +// the program if located at a start address other than 0. +// +//***************************************************************************** +#pragma DATA_SECTION(g_pfnVectors, ".intvecs") +void (* const g_pfnVectors[])(void) = +{ + (void (*)(void))((uint32_t)&__STACK_TOP), + // The initial stack pointer + ResetISR, // The reset handler + NmiSR, // The NMI handler + FaultISR, // The hard fault handler + IntDefaultHandler, // The MPU fault handler + IntDefaultHandler, // The bus fault handler + IntDefaultHandler, // The usage fault handler + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + IntDefaultHandler, // SVCall handler + IntDefaultHandler, // Debug monitor handler + 0, // Reserved + IntDefaultHandler, // The PendSV handler + IntDefaultHandler, // The SysTick handler + IntDefaultHandler, // GPIO Port A + IntDefaultHandler, // GPIO Port B + IntDefaultHandler, // GPIO Port C + IntDefaultHandler, // GPIO Port D + IntDefaultHandler, // GPIO Port E + IntDefaultHandler, // UART0 Rx and Tx + IntDefaultHandler, // UART1 Rx and Tx + IntDefaultHandler, // SSI0 Rx and Tx + IntDefaultHandler, // I2C0 Master and Slave + IntDefaultHandler, // PWM Fault + IntDefaultHandler, // PWM Generator 0 + IntDefaultHandler, // PWM Generator 1 + IntDefaultHandler, // PWM Generator 2 + IntDefaultHandler, // Quadrature Encoder 0 + IntDefaultHandler, // ADC Sequence 0 + IntDefaultHandler, // ADC Sequence 1 + IntDefaultHandler, // ADC Sequence 2 + IntDefaultHandler, // ADC Sequence 3 + IntDefaultHandler, // Watchdog timer + IntDefaultHandler, // Timer 0 subtimer A + IntDefaultHandler, // Timer 0 subtimer B + IntDefaultHandler, // Timer 1 subtimer A + IntDefaultHandler, // Timer 1 subtimer B + IntDefaultHandler, // Timer 2 subtimer A + IntDefaultHandler, // Timer 2 subtimer B + IntDefaultHandler, // Analog Comparator 0 + IntDefaultHandler, // Analog Comparator 1 + IntDefaultHandler, // Analog Comparator 2 + IntDefaultHandler, // System Control (PLL, OSC, BO) + IntDefaultHandler, // FLASH Control + IntDefaultHandler, // GPIO Port F + IntDefaultHandler, // GPIO Port G + IntDefaultHandler, // GPIO Port H + IntDefaultHandler, // UART2 Rx and Tx + IntDefaultHandler, // SSI1 Rx and Tx + IntDefaultHandler, // Timer 3 subtimer A + IntDefaultHandler, // Timer 3 subtimer B + IntDefaultHandler, // I2C1 Master and Slave + IntDefaultHandler, // Quadrature Encoder 1 + IntDefaultHandler, // CAN0 + IntDefaultHandler, // CAN1 + 0, // Reserved + 0, // Reserved + IntDefaultHandler, // Hibernate + IntDefaultHandler, // USB0 + IntDefaultHandler, // PWM Generator 3 + IntDefaultHandler, // uDMA Software Transfer + IntDefaultHandler, // uDMA Error + IntDefaultHandler, // ADC1 Sequence 0 + IntDefaultHandler, // ADC1 Sequence 1 + IntDefaultHandler, // ADC1 Sequence 2 + IntDefaultHandler, // ADC1 Sequence 3 + 0, // Reserved + 0, // Reserved + IntDefaultHandler, // GPIO Port J + IntDefaultHandler, // GPIO Port K + IntDefaultHandler, // GPIO Port L + IntDefaultHandler, // SSI2 Rx and Tx + IntDefaultHandler, // SSI3 Rx and Tx + IntDefaultHandler, // UART3 Rx and Tx + IntDefaultHandler, // UART4 Rx and Tx + IntDefaultHandler, // UART5 Rx and Tx + IntDefaultHandler, // UART6 Rx and Tx + IntDefaultHandler, // UART7 Rx and Tx + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + IntDefaultHandler, // I2C2 Master and Slave + IntDefaultHandler, // I2C3 Master and Slave + IntDefaultHandler, // Timer 4 subtimer A + IntDefaultHandler, // Timer 4 subtimer B + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + IntDefaultHandler, // Timer 5 subtimer A + IntDefaultHandler, // Timer 5 subtimer B + IntDefaultHandler, // Wide Timer 0 subtimer A + IntDefaultHandler, // Wide Timer 0 subtimer B + IntDefaultHandler, // Wide Timer 1 subtimer A + IntDefaultHandler, // Wide Timer 1 subtimer B + IntDefaultHandler, // Wide Timer 2 subtimer A + IntDefaultHandler, // Wide Timer 2 subtimer B + IntDefaultHandler, // Wide Timer 3 subtimer A + IntDefaultHandler, // Wide Timer 3 subtimer B + IntDefaultHandler, // Wide Timer 4 subtimer A + IntDefaultHandler, // Wide Timer 4 subtimer B + IntDefaultHandler, // Wide Timer 5 subtimer A + IntDefaultHandler, // Wide Timer 5 subtimer B + IntDefaultHandler, // FPU + 0, // Reserved + 0, // Reserved + IntDefaultHandler, // I2C4 Master and Slave + IntDefaultHandler, // I2C5 Master and Slave + IntDefaultHandler, // GPIO Port M + IntDefaultHandler, // GPIO Port N + IntDefaultHandler, // Quadrature Encoder 2 + 0, // Reserved + 0, // Reserved + IntDefaultHandler, // GPIO Port P (Summary or P0) + IntDefaultHandler, // GPIO Port P1 + IntDefaultHandler, // GPIO Port P2 + IntDefaultHandler, // GPIO Port P3 + IntDefaultHandler, // GPIO Port P4 + IntDefaultHandler, // GPIO Port P5 + IntDefaultHandler, // GPIO Port P6 + IntDefaultHandler, // GPIO Port P7 + IntDefaultHandler, // GPIO Port Q (Summary or Q0) + IntDefaultHandler, // GPIO Port Q1 + IntDefaultHandler, // GPIO Port Q2 + IntDefaultHandler, // GPIO Port Q3 + IntDefaultHandler, // GPIO Port Q4 + IntDefaultHandler, // GPIO Port Q5 + IntDefaultHandler, // GPIO Port Q6 + IntDefaultHandler, // GPIO Port Q7 + IntDefaultHandler, // GPIO Port R + IntDefaultHandler, // GPIO Port S + IntDefaultHandler, // PWM 1 Generator 0 + IntDefaultHandler, // PWM 1 Generator 1 + IntDefaultHandler, // PWM 1 Generator 2 + IntDefaultHandler, // PWM 1 Generator 3 + IntDefaultHandler // PWM 1 Fault +}; + +//***************************************************************************** +// +// This is the code that gets called when the processor first starts execution +// following a reset event. Only the absolutely necessary set is performed, +// after which the application supplied entry() routine is called. Any fancy +// actions (such as making decisions based on the reset cause register, and +// resetting the bits in that register) are left solely in the hands of the +// application. +// +//***************************************************************************** +void +ResetISR(void) +{ + // + // Jump to the CCS C initialization routine. This will enable the + // floating-point unit as well, so that does not need to be done here. + // + __asm(" .global _c_int00\n" + " b.w _c_int00"); +} + +//***************************************************************************** +// +// This is the code that gets called when the processor receives a NMI. This +// simply enters an infinite loop, preserving the system state for examination +// by a debugger. +// +//***************************************************************************** +static void +NmiSR(void) +{ + // + // Enter an infinite loop. + // + while(1) + { + } +} + +//***************************************************************************** +// +// This is the code that gets called when the processor receives a fault +// interrupt. This simply enters an infinite loop, preserving the system state +// for examination by a debugger. +// +//***************************************************************************** +static void +FaultISR(void) +{ + // + // Enter an infinite loop. + // + while(1) + { + } +} + +//***************************************************************************** +// +// This is the code that gets called when the processor receives an unexpected +// interrupt. This simply enters an infinite loop, preserving the system state +// for examination by a debugger. +// +//***************************************************************************** +static void +IntDefaultHandler(void) +{ + // + // Go into an infinite loop. + // + while(1) + { + } +}