/***************************************************************************** * Product: Simple Blinky example, Tiva EK-TM4C123GXL, Vanilla kernel * Last Updated for Version: 5.1.1 * Date of the Last Update: Oct 09, 2013 * * Q u a n t u m L e a P s * --------------------------- * innovating embedded systems * * Copyright (C) 2002-2013 Quantum Leaps, LLC. All rights reserved. * * This program is open source software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * Alternatively, this program may be distributed and modified under the * terms of Quantum Leaps commercial licenses, which expressly supersede * the GNU General Public License and are specifically designed for * licensees interested in retaining the proprietary status of their code. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Contact information: * Quantum Leaps Web sites: http://www.quantum-leaps.com * http://www.state-machine.com * e-mail: info@quantum-leaps.com *****************************************************************************/ #include "qp_port.h" #include "bsp.h" #include "tm4c_cmsis.h" /* Tiva-C CMSIS-compliant interface */ #include "sysctl.h" #include "gpio.h" #include "rom.h" Q_DEFINE_THIS_FILE /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority(). * DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE! */ enum KernelUnawareISRs { /* see NOTE00 */ /* ... */ MAX_KERNEL_UNAWARE_CMSIS_PRI /* keep always last */ }; /* "kernel-unaware" interrupts can't overlap "kernel-aware" interrupts */ Q_ASSERT_COMPILE(MAX_KERNEL_UNAWARE_CMSIS_PRI <= QF_AWARE_ISR_CMSIS_PRI); enum KernelAwareISRs { SYSTICK_PRIO = QF_AWARE_ISR_CMSIS_PRI, /* see NOTE00 */ /* ... */ MAX_KERNEL_AWARE_CMSIS_PRI /* keep always last */ }; /* "kernel-aware" interrupts should not overlap the PendSV priority */ Q_ASSERT_COMPILE(MAX_KERNEL_AWARE_CMSIS_PRI <= (0xFF >>(8-__NVIC_PRIO_BITS))); /* LEDs and Switches of the EK-TM4C123GXL board ............................*/ #define LED_RED (1U << 1) #define LED_GREEN (1U << 3) #define LED_BLUE (1U << 2) #define USR_SW1 (1U << 4) #define USR_SW2 (1U << 0) /* ISRs defined in this BSP ------------------------------------------------*/ void SysTick_Handler(void); void assert_failed(char const *file, int line); /*..........................................................................*/ void SysTick_Handler(void) { /* system clock tick ISR */ QF_TICK_X(0U, (void *)0); /* process all armed time events */ } /*..........................................................................*/ void BSP_init(void) { /* Enable the floating-point unit */ SCB->CPACR |= (0xFU << 20); /* Enable lazy stacking for interrupt handlers. This allows FPU * instructions to be used within interrupt handlers, but at the * expense of extra stack and CPU usage. */ FPU->FPCCR |= (1U << FPU_FPCCR_ASPEN_Pos) | (1U << FPU_FPCCR_LSPEN_Pos); /* Set the clocking to run directly from the crystal */ ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); /* enable clock to the peripherals used by the application */ SYSCTL->RCGC2 |= (1U << 5); /* enable clock to GPIOF */ __NOP(); /* wait after enabling clocks */ __NOP(); __NOP(); /* configure the LEDs and push buttons */ GPIOF->DIR |= (LED_RED | LED_GREEN | LED_BLUE);/* set direction: output */ GPIOF->DEN |= (LED_RED | LED_GREEN | LED_BLUE); /* digital enable */ GPIOF->DATA_Bits[LED_RED] = 0; /* turn the LED off */ GPIOF->DATA_Bits[LED_GREEN] = 0; /* turn the LED off */ GPIOF->DATA_Bits[LED_BLUE] = 0; /* turn the LED off */ /* configure the User Switches */ GPIOF->DIR &= ~(USR_SW1 | USR_SW2); /* set direction: input */ ROM_GPIOPadConfigSet(GPIO_PORTF_BASE, (USR_SW1 | USR_SW2), GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); if (QS_INIT((void *)0) == 0) { /* initialize the QS software tracing */ Q_ERROR(); } QS_RESET(); QS_OBJ_DICTIONARY(&l_SysTick_Handler); } /*..........................................................................*/ void BSP_ledOff() { GPIOF->DATA_Bits[LED_GREEN] = 0U; } /*..........................................................................*/ void BSP_ledOn() { GPIOF->DATA_Bits[LED_GREEN] = LED_GREEN; } /*..........................................................................*/ void QF_onStartup(void) { /* set up the SysTick timer to fire at BSP_TICKS_PER_SEC rate */ SysTick_Config(ROM_SysCtlClockGet() / BSP_TICKS_PER_SEC); /* assing all priority bits for preemption-prio. and none to sub-prio. */ NVIC_SetPriorityGrouping(0U); /* set priorities of ALL ISRs used in the system, see NOTE00 * * !!!!!!!!!!!!!!!!!!!!!!!!!!!! CAUTION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! * Assign a priority to EVERY ISR explicitly by calling NVIC_SetPriority(). * DO NOT LEAVE THE ISR PRIORITIES AT THE DEFAULT VALUE! */ NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIO); /* ... */ /* enable IRQs... */ } /*..........................................................................*/ void QF_onCleanup(void) { } /*..........................................................................*/ void QF_onIdle(void) { /* called with interrupts disabled, see NOTE01 */ #ifdef NDEBUG /* Put the CPU and peripherals to the low-power mode. * you might need to customize the clock management for your application, * see the datasheet for your particular Cortex-M MCU. */ QF_CPU_SLEEP(); /* atomically go to sleep and enable interrupts */ #else QF_INT_ENABLE(); /* just enable interrupts */ #endif } /*..........................................................................*/ void Q_onAssert(char const Q_ROM * const Q_ROM_VAR file, int line) { (void)file; /* avoid compiler warning */ (void)line; /* avoid compiler warning */ QF_INT_DISABLE(); /* make sure that all interrupts are disabled */ for (;;) { /* NOTE: replace the loop with reset for final version */ } } /*..........................................................................*/ /* error routine that is called if the CMSIS library encounters an error */ void assert_failed(char const *file, int line) { Q_onAssert(file, line); } /***************************************************************************** * NOTE00: * The QF_AWARE_ISR_CMSIS_PRI constant from the QF port specifies the highest * ISR priority that is disabled by the QF framework. The value is suitable * for the NVIC_SetPriority() CMSIS function. * * Only ISRs prioritized at or below the QF_AWARE_ISR_CMSIS_PRI level (i.e., * with the numerical values of priorities equal or higher than * QF_AWARE_ISR_CMSIS_PRI) are allowed to call any QF services. These ISRs * are "QF-aware". * * Conversely, any ISRs prioritized above the QF_AWARE_ISR_CMSIS_PRI priority * level (i.e., with the numerical values of priorities less than * QF_AWARE_ISR_CMSIS_PRI) are never disabled and are not aware of the kernel. * Such "QF-unaware" ISRs cannot call any QF services. The only mechanism * by which a "QF-unaware" ISR can communicate with the QF framework is by * triggering a "QF-aware" ISR, which can post/publish events. * * NOTE01: * The QF_onIdle() callback is called with interrupts disabled, because the * determination of the idle condition might change by any interrupt posting * an event. QF::onIdle() must internally enable interrupts, ideally * atomically with putting the CPU to the power-saving mode. */