On a bare metal system you often need to protect code with a critical section.
Here is an article describing what I need.
mcuoneclipse.com/.../
At the end, the author provides an example. Try as I might, I cannot get this or variants to compile with KEIL. Can anyone help? I am looking for the solution to work with C++.
Thanks
Rich
Here are the specifics on the KEIL tool that I am using. IDE-Version: µVision V5.22.0.0
Tool Version Numbers: Toolchain: MDK-Lite Version: 5.22 Toolchain Path: C:\Keil_v5\ARM\ARMCC\Bin C Compiler: Armcc.exe V5.06 update 4 (build 422) Assembler: Armasm.exe V5.06 update 4 (build 422) Linker/Locator: ArmLink.exe V5.06 update 4 (build 422) Library Manager: ArmAr.exe V5.06 update 4 (build 422) Hex Converter: FromElf.exe V5.06 update 4 (build 422) CPU DLL: SARMCM3.DLL V5.22 Dialog DLL: DARMCM1.DLL V1.15.0.0 Target DLL: UL2CM3.DLL V1.159.0.0 Dialog DLL: TARMCM1.DLL V1.11.0.0
Code:
#define CpuCriticalVar() uint8_t cpuSR #define CpuEnterCritical() \ do { \ asm ( \ "MRS R0, PRIMASK\n\t" \ "CPSID I\n\t" \ "STRB R0, %[output]" \ : [output] "=m" (cpuSR) :: "r0"); \ } while(0) #define CpuExitCritical() \ do{ \ asm ( \ "ldrb r0, %[input]\n\t" \ "msr PRIMASK,r0;\n\t" \ ::[input] "m" (cpuSR) : "r0"); \ } while(0)
Test code
#if 0 /* original, buggy version */ #define DEFINE_CRITICAL() /* nothing */ #define ENTER_CRITICAL() EnterCritical() #define EXIT_CRITICAL() ExitCritical() #else /* fixed version using local variable */ #define DEFINE_CRITICAL() CpuCriticalVar() #define ENTER_CRITICAL() CpuEnterCritical() #define EXIT_CRITICAL() CpuExitCritical() #endif static volatile uint8_t shared=0; static void Error(void) { for(;;); } void T1(void) { /* called by timer interrupt every 0.1 ms, max prio (0) */ DEFINE_CRITICAL(); ENTER_CRITICAL(); shared += 1; if (shared!=1) { Error(); } shared -= 1; EXIT_CRITICAL(); } void T2(void) { /* called by timer interrupt every 1 ms, minimal prio (3) */ DEFINE_CRITICAL(); ENTER_CRITICAL(); shared += 1; if (shared!=1) { Error(); } shared -= 1; EXIT_CRITICAL(); } static void test(void) { DEFINE_CRITICAL(); for(;;) { ENTER_CRITICAL(); shared += 1; if (shared!=1) { Error(); } shared -= 1; EXIT_CRITICAL(); } }
Pity the author didn't figure out why his ring buffer implementation was broken. Looks like incrementing and decrementing the size in two places can bite you.