Quantum Leaps 9d72aa81de 5.2.0
2013-12-30 17:41:15 -05:00

203 lines
8.6 KiB
C++

//****************************************************************************
// Product: Simple Blinky example, Tiva EK-TM4C123GXL, Vanilla kernel
// Last Updated for Version: 5.2.0
// Date of the Last Update: Dec 28, 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 3 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 <http://www.gnu.org/licenses/>.
//
// 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"
extern "C" {
#include "tm4c_cmsis.h" // Tiva-C CMSIS-compliant interface
#include "sysctl.h"
#include "gpio.h"
#include "rom.h"
}
using namespace QP;
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 --------------------------------------------------
extern "C" void SysTick_Handler(void);
//............................................................................
extern "C" 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_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
}
//............................................................................
extern "C" void Q_onAssert(char const Q_ROM * const file, int_t line) {
assert_failed(file, line);
}
//............................................................................
// error routine that is called if the CMSIS library encounters an error
extern "C" void assert_failed(char const *file, int line) {
(void)file; // avoid compiler warning
(void)line; // avoid compiler warning
QF_INT_DISABLE(); // make sure that all interrupts are disabled
ROM_SysCtlReset(); // reset the system
}
//****************************************************************************
// 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.
//