Table of Contents
The ARMv7-M Port
This port includes support for all devices using one of the following cores:
- Cortex-M3
- Cortex-M4
- Cortex-M7
Port Features
The core supports the following features:
- FPU support, single precision on the M7, both single and double precision on the M7.
- Two IRQ priority modes:
- Simplified priority.
- Partial masking.
- MPU support for stack overflow checking.
- MPU context switch support.
- RTC support using the internal
CYCCNT
counter. - Support of
WFI
instruction in the idle thread in order to reduce power consumption. - Support of
SVC
instruction for system call support. This is used by the ChibiOS/SB add-on but it is also available to advanced users.
Assumptions
The port makes some assumptions.
IRQ Priority Groups
Standard port settings do not support priority groups larger than one bit (no priority grouping). This is enforced in the port initialization code.
IRQ Priorities Range
IRQ priorities are handled as an uniform range starting from 0 (highest priority) up to N-1 (lowest priority). N is equal to 2p, p is the number of implemented priority bits in the NVIC.
When CORTEX_SIMPLIFIED_PRIORITY
is set to FALSE
then priorities zero and one are reserved for fast interrupts, no OS code must be used in associated ISRs. In addition, priority level two is reserved and should not be used.
IRQ Priority Ordering
The port relies on the lowest priority ISR in a IRQ chain to perform the final reschedule operation, this is done in the CH_IRQ_EPILOGUE()
macro. This means that all ISRs must use the OS macros or the system would not be able to reschedule under certain conditions which is an hard error.
Note that “naked” ISRs are allowed but must have higher priority than any OS-aware ISR.
Stacks Setup
The port is meant to work with the Cortex-M in dual stack mode. It is responsibility of startup files to enable the dual stack mode and setup appropriate stack areas. The PSP stack is used for the main()
thread, the main stack is used for exceptions and IRQs processing.
FPU Support
Enabling FPU requires a mix of settings in various layers.
- The compiler needs the correct options.
- The startup files need to perform the correct initializations.
- The Port Layer needs its own settings.
- Makefile settings.
Compiler Settings
Each compiler is different but in general you need to switch from SW floating point to HW floating point, there could be multiple FP modes to choose from.
Startup Initializations
FPU-related initialization are expected to be performed in the compiler startup files. ChibiOS-provided startup files make all the required initialization, no need to modify anything.
Port Layer Settings
FPU support can be enabled by defining CORTEX_USE_FPU=1
, if an FPU is not present in the current device then a compile time error is generated. Enabling FPU support uses more RAM and makes context switch slower, it should be avoided if your application does not require it.
Makefile Settings
Note that in all demos the FPU can simply be enabled in makefiles by setting USE_FPU = hard
, the makefile takes care of setting CORTEX_USE_FPU=1
in addition to passing to the compiler all the required options.
IRQ Priority Modes
The ARMv7-M port supports two different methods for implementing critical sections.
Simplified Priority
This mode is selected by setting CORTEX_SIMPLIFIED_PRIORITY
to TRUE
in chconf.h
. This methods disables/enables all interrupts using the CPSID
instruction. All interrupts are disabled when entering a critical section and are enabled when exiting.
This method is very simple and makes the kernel slightly faster and smaller, use it if your application does not need “fast interrupts”.
Partial Masking
This is the default mode, critical sections are implemented by modifying the base priority using the BASEPRI
register. In this mode not all priority levels are equal:
- Priority levels 0..1 (highest) are reserved for fast interrupts. Fast interrupt ISRs cannot use any RTOS function or macros because the kernel itself can be preempted by those. Fast interrupts have minimum latency and are not affected by RTOS critical sections.
- Priority level 2 is reserved for context switch, it is recommended to not use it.
- Priority levels 3..N are the normal priority range that can be used by IRQ sources needing to interact with RTOS services. N depends on how many IRQ bits are implemented in your device, 4 bits is very common so N is usually 15.
MPU Stack Overflow Checking
By setting PORT_ENABLE_GUARD_PAGES
and CH_DBG_ENABLE_STACK_CHECK
to TRUE
in chconf.h
then the MPU is enabled for stack overflow checking. A guard page of 32 bytes is placed at the bottom of all threads working areas, an eventual stack overflow is caught by an exception. MPU region 7 is used by default by this feature.
MPU Context Switch Support
It is possible to associate up to 4 MPU regions (0…N-1) to the thread context by setting the option PORT_SWITCHED_REGIONS_NUMBER
to N
in chconf.h
, This option makes it possible for each thread to have up to 4 private MPU regions, regions are swapped on the fly on context switch.
RTC Support
The port supports the realtime counter feature using the DWT→CYCCNT
counter. This port feature is used by the RT kernel for time measurement and statistics, no need to enable anything, it is always available.
WFI Instruction Support
Setting CORTEX_ENABLE_WFI_IDLE
to TRUE
in chconf.h
inserts a WFI
instruction in the system idle loop. This can be used for advanced power management.
SVC System Call Support
By setting PORT_USE_SYSCALL
to TRUE
in chconf.h
the support for SVC
instruction for system calls is enabled. This option causes the invocation of a system call handler if some thread in non-privileged mode executes SVC
:
The syscall handler has to be declared as follow:
void port_syscall(struct port_extctx *ctxp, uint32_t n) { (void)ctxp; (void)n; chSysHalt("svc"); }
This option is for experts only, it is there because ChibiOS/SB requires this kind of support.