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.