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.
View all questions in Keil forum