Version V3.07.00 of µC/OS-III and V2.92.16 of µC/OS-II brought a few changes and improvements to the ARMv7-M port, which provides support for Cortex-M3, M4, and M7 architectures. The changes are simple Folder/File structure modifications to µC/CPU and µC/OS-III as well as additional configuration defines. Moreover, the new functionality of the port allows the user to specify a boundary for Kernel aware and Non-Kernel aware ISR's by taking advantage of the BASEPRI register.
Requirements
| Module | Version |
| µC/OS-II | V2.92.16 or newer |
| µC/OS-III | V3.07.00 or newer |
| µC/CPU | V1.31.04 or newer |
| µC/LIB | V1.38.02 or newer |
Modifications
In µC/CPU version V1.31.04, the Cortex-M3 and M4 ports were merged into a single port named ‘ARM-Cortex-M/ARMv7-M/’ as shown in the image below. This was done to simplify file updates and to allow minimally intrusive migrations between the Cortex-M3 and M4 folders. In addition, the ARMv7-M port provides support for the Cortex-M7 family.
|
Figure 1. |
Due to folder modifications in µC/CPU, please make sure to update your project include path to ‘uC-CPU\ARM-Cortex-M\ARMv7-M\<compiler>. If your project is currently using some register defines from ‘cpu.h’ such as SYSTICK, or NVIC registers you will need to update them to their new names accordingly.
‘cpu_cfg.h’ adds two additional defines where CPU_CFG_KA_IPL_BOUNDARY determines the interrupt priority level that establishes the boundary for ISRs that are kernel-aware and Non-Kernel-aware. The second additional define, CPU_CFG_NVIC_PRIO_BITS, determines the interrupt programmable priority levels, which is normally specified in the MCU reference manual or an application note provided by the MCU vendor as shown below.
|
Figure 2. |
CPU_CFG_NVIC_PRIO_BITS is set to the number of bits that are not reserved in the BASEPRI register. If we follow Figure 2 then It will be 4 since we can only write to bits [7-4]. Another way to determine the value for this define is through the Interrupt Priority Register(NVIC_IPRx) as shown in Figure 3, where bits[7:4] are implemented for each IRQx; therefore, CPU_CFG_NVIC_PRIO_BITS will be set to 4.
|
Figure 3. |
CPU_CFG_KA_IPL_BOUNDARY defines the value to be used for BASEPRI, which defines the minimum priority for exception processing. A nonzero value for BASEPRI prevents the activation of all exceptions with the same or lower priority level as the BASEPRI value, so if BASEPRI is set to 3 then exceptions with priority level 3 to 15 will be disabled. Moreover, interrupt priority levels between 3-15 will be considered Kernel aware, while the other ones will be Non-Kernel aware.
From the application point of view, the user will need to initialize all the external Interrupt priorities to CPU_CFG_KA_IPL_BOUNDARY using the proper NVIC_IPRx register. This will prevent any unexpected behavior from the application such as not modifying the interrupt priorities that are originally set to zero. In addition, template files, such as bsp_int.h and bsp_int_armv7m.c will demonstrate the initialization of all interrupt priorities to the IPL boundary, as well as API's for registering the ISR handlers into the vector table. Please make sure you are using the module version mentioned at the beginning of the document.
Due to the new ARMv7-M port modifications, the function CPU_IntSrcPrioSet() has been modified to allow the user to properly set the interrupt priority level of the ISR handler while taking into consideration the ISR type (Kernel/Non-Kernel aware). The user is strongly recommended to use the provided API's to always remember the type of ISR the application will be using/setting.
µC/OS-II or µC/OS-III
When using µC/OS-II, you will need to include ‘cpu_cfg.h’ into ‘app_cfg.h’ since µC/OS-II is dependent on this file. In terms of file/folder structure changes, the new ARMv7-M port uses a generic ‘os_cpu_c.c’ for all compilers. The new functionality of the port allows support for Kernel and Non-Kernel aware ISRs by taking advantage of the BASEPRI register. This allows the port to specify a boundary for ISRs as previously explained using the CPU_CFG_KA_IPL_BOUNDARY. Kernel Aware is described as an ISR that makes calls to OS kernel services, such as semaphores, mutexes, flags, etc. You may also hear it referred to as synchronous interrupts. The proper handler/implementation when using the OS is shown below.
void KA_ISR_Handler (void)
{
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
OSIntEnter(); /* Tell OS that we are starting an ISR */
CPU_CRITICAL_EXIT();
/* HANDLE YOUR ISR HERE */
/* HANDLE YOUR ISR HERE */
OSIntExit(); /* Tell OS that we are leaving the ISR */
}
Non-Kernel Aware can be described as Fast ISRs, which do not require any kind of OS kernel service calls. They are also referred to as asynchronous interrupts. The proper handler implementation when using the OS is shown below.
void NKA_ISR_Handler (void)
{
/* HANDLE YOUR ISR HERE */
/* HANDLE YOUR ISR HERE */
}
Summary
⦁ Make sure to use the Module versions mentioned at the beginning of the document.
⦁ Update your folder structure and project include path options.
⦁ CPU_CFG_KA_IPL_BOUNDARY and CPU_CFG_NVIC_PRIO_BITS should be defined in ‘cpu_cfg.h’ and be given a proper value.
⦁ Set all external interrupt priorities to CPU_CFG_KA_IPL_BOUNDARY using the NVIC_IPRx register. The template files have this implementation for customer reference or use.
⦁ Determine how to declare your Kernel-Aware/Non-Kernel Aware ISR handlers based on the application needs.


