mirror of
https://github.com/QuantumLeaps/qpcpp.git
synced 2025-02-04 06:13:00 +08:00
151 lines
6.0 KiB
C
151 lines
6.0 KiB
C
/// @file
|
|
/// @brief QF/C++ port to ARM Cortex-M, preemptive QK kernel, TI-ARM toolset
|
|
/// @cond
|
|
///***************************************************************************
|
|
/// Last updated for version 5.4.0
|
|
/// Last updated on 2015-05-04
|
|
///
|
|
/// Q u a n t u m L e a P s
|
|
/// ---------------------------
|
|
/// innovating embedded systems
|
|
///
|
|
/// Copyright (C) Quantum Leaps, www.state-machine.com.
|
|
///
|
|
/// 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:
|
|
/// Web: www.state-machine.com
|
|
/// Email: info@state-machine.com
|
|
///***************************************************************************
|
|
/// @endcond
|
|
|
|
#ifndef qf_port_h
|
|
#define qf_port_h
|
|
|
|
// The maximum number of active objects in the application, see NOTE1
|
|
#define QF_MAX_ACTIVE 32
|
|
|
|
// The maximum number of system clock tick rates
|
|
#define QF_MAX_TICK_RATE 2
|
|
|
|
// is the target M3 or M4? see NOTE2
|
|
#if (defined __TI_TMS470_V7M3__) || (defined __TI_TMS470_V7M4__)
|
|
|
|
// BASEPRI limit for QF-aware ISR priorities, see NOTE3
|
|
#define QF_BASEPRI (0xFFU >> 2)
|
|
|
|
// QF-aware ISR priority for CMSIS function NVIC_SetPriority(), NOTE4
|
|
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
|
|
|
// QF interrupt disable/enable, NOTE: keep in sync with QF_BASEPRI!!!
|
|
#define QF_INT_DISABLE() __asm( \
|
|
" PUSH {R0}\n\r" \
|
|
" MOV R0,#0x3F\n\r" \
|
|
" MSR BASEPRI,R0\n\r" \
|
|
" POP {R0}")
|
|
|
|
#define QF_INT_ENABLE() __asm( \
|
|
" PUSH {R0}\n\r" \
|
|
" MOV R0,#0\n\r" \
|
|
" MSR BASEPRI,R0\n\r" \
|
|
" POP {R0}")
|
|
|
|
// the intrinsic function _norm() generates the CLZ instruction
|
|
#define QF_LOG2(n_) ((uint8_t)(32U - _norm(n_)))
|
|
|
|
// macro to put the CPU to sleep inside QF_onIdle()
|
|
#define QF_CPU_SLEEP() do { \
|
|
__asm(" CPSID I"); \
|
|
QF_INT_ENABLE(); \
|
|
__asm(" WFI"); \
|
|
__asm(" CPSIE I"); \
|
|
} while (0)
|
|
|
|
// not M3 or M4, assuming no BASEPRI register or CLZ instruction
|
|
#else
|
|
|
|
// QF interrupt disable/enable
|
|
#define QF_INT_DISABLE() __asm(" CPSID I")
|
|
#define QF_INT_ENABLE() __asm(" CPSIE I")
|
|
|
|
// QF-aware ISR priority for CMSIS function NVIC_SetPriority(), NOTE5
|
|
#define QF_AWARE_ISR_CMSIS_PRI 0
|
|
|
|
// macro to put the CPU to sleep inside QF_idle()
|
|
#define QF_CPU_SLEEP() do { \
|
|
__asm(" WFI"); \
|
|
QF_INT_ENABLE(); \
|
|
} while (0)
|
|
|
|
#endif // (defined __TI_TMS470_V7M3__) || (defined __TI_TMS470_V7M4__)
|
|
|
|
// QF critical section entry/exit
|
|
// QF_CRIT_STAT_TYPE not defined: unconditional interrupt enabling" policy
|
|
#define QF_CRIT_ENTRY(dummy) QF_INT_DISABLE()
|
|
#define QF_CRIT_EXIT(dummy) QF_INT_ENABLE()
|
|
#define QF_CRIT_EXIT_NOP() __asm(" NOP")
|
|
|
|
#include "qep_port.h" // QEP port
|
|
#include "qk_port.h" // QK preemptive kernel port
|
|
#include "qf.h" // QF platform-independent public interface
|
|
|
|
//****************************************************************************
|
|
// NOTE1:
|
|
// The maximum number of active objects QF_MAX_ACTIVE can be increased
|
|
// up to 63, if necessary. Here it is set to a lower level to save some RAM.
|
|
//
|
|
// NOTE2:
|
|
// On Cortex-M3/M4/M4F, the interrupt disable/enable policy uses the BASEPRI
|
|
// register (which is not implemented in Cortex-M0/M0+/M1) to disable
|
|
// interrupts only with priority lower than the level specified by the
|
|
// QF_BASEPRI macro. The interrupts with priorities above QF_BASEPRI (i.e.,
|
|
// with numerical priority values lower than QF_BASEPRI) are not disabled in
|
|
// this method. These free-running interrupts are not allowed to call any QF
|
|
// services, because QF is not aware of these interrupts. Coversely, only
|
|
// "QF-aware" interrupts, with numerical values of priorities eqal to or
|
|
// higher than QF_BASEPRI, can call QF services.
|
|
//
|
|
// NOTE3:
|
|
// For Cortex-M3/M4/M4F, the macro QF_BASEPRI leaves the top 2 priority bits
|
|
// empty for QF-aware interrupts. This is the highest-possible priority
|
|
// (lowest possible numerical value) for the guaranteed 3 priority bits
|
|
// implemented in the NVIC.
|
|
//
|
|
// NOTE4:
|
|
// The QF_AWARE_ISR_CMSIS_PRI macro is useful as an offset for enumerating
|
|
// the QF-aware interrupt priority levels in the applications, whereas the
|
|
// numerical values of the QF-aware interrupts must be greater or equal to
|
|
// QF_AWARE_ISR_CMSIS_PRI. The enumerated values based on
|
|
// QF_AWARE_ISR_CMSIS_PRI can be passed directly to the CMSIS function
|
|
// NVIC_SetPriority(), which shifts them by (8 - __NVIC_PRIO_BITS) into the
|
|
// correct bit position, while __NVIC_PRIO_BITS is the CMSIS macro defining
|
|
// the number of implemented priority bits in the NVIC. Please note that
|
|
// the macro QF_AWARE_ISR_CMSIS_PRI is intended only for applications and
|
|
// is not used inside the QF port, which remains generic and not dependent
|
|
// on the number of implemented priority bits in the NVIC.
|
|
//
|
|
// NOTE5:
|
|
// On Cortex-M0/M0+/M1 (architecture v6-M, v6S-M), the interrupt disabling
|
|
// policy uses the PRIMASK register to disable interrupts globally. The
|
|
// QF_AWARE_ISR_CMSIS_PRI level is zero, meaning that all interrupts are
|
|
// "kernel-aware".
|
|
//
|
|
|
|
#endif // qf_port_h
|