CriticalSection Component

I have created and published on GitHub a new component ‘CriticalSection’:

Critical Section Component Methods

Critical Section Component Methods

This component is a wrapper between my components and the problematic current implementation in Processor Expert (see EnterCritical() and ExitCritical(): Why Things are Failing Badly). It uses a flexible approach and uses macros to either use my modified version of EnterCritical() and ExitCritical(), or simply defaults to the original implementation.

Implementation

The driver source code is available on GitHub here.

For ARM Cortex, the implementation is as below:

#define CS1_CriticalVariable() \
  uint8_t cpuSR; /* variable to store current status */

/*
** ===================================================================
**     Method      :  CS1_CriticalVariable (component CriticalSection)
**     Description :
**         Defines a variable if necessary. This is a macro.
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/

#define CS1_EnterCritical() \
  do {                                  \
    asm (                               \
    "MRS   R0, PRIMASK\n\t"             \
    "CPSID I\n\t"                       \
    "STRB R0, %[output]"                \
    : [output] "=m" (cpuSR) :: "r0");   \
  } while(0)

/*
** ===================================================================
**     Method      :  CS1_EnterCritical (component CriticalSection)
**     Description :
**         Enters a critical section
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/

#define CS1_ExitCritical() \
  do{                                  \
    asm (                              \
    "ldrb r0, %[input]\n\t"            \
    "msr PRIMASK,r0;\n\t"              \
    ::[input] "m" (cpuSR) : "r0");     \
  } while(0)

/*
** ===================================================================
**     Method      :  CS1_ExitCritical (component CriticalSection)
**     Description :
**         Exits a critical section
**     Parameters  : None
**     Returns     : Nothing
** ===================================================================
*/

Usage

The component source implements three macros:

  1. CriticalVariable() is a macro who declares and defines a local variable to store the current interrupt state.
  2. EnterCritical() is a macro to create a critical section.
  3. ExitCritical() leaves the critical section.

Below shows how I used it: it defines the local critical variable, and uses EnterCritical() and ExitCritical() to protect a critical section:

void TMOUT1_LeaveCounter(TMOUT1_CounterHandle handle)
{
  CS1_CriticalVariable()

  if (handle==TMOUT1_OUT_OF_HANDLE) {
    return;
  }
  CS1_EnterCritical();
  TMOUT1_Counters[handle] = 0;
  TMOUT1_FreeCounters[handle]=TRUE;
  CS1_ExitCritical();
}

Upgrading

Several components have now added an extra interface to the new Critical Section component. Components include the Shell, RingBuffer, Trigger, Timeout and SimpleEvent components.

CriticalSection Interface in Shell

CriticalSection Interface in Shell

Upgrading is easy: simply select to add the new component (or use the already added one):

New Component CriticalSection

New Component CriticalSection

That’s it :-).

Summary

I have created that new CriticalSection component to avoid an obvious problem with the default Processor Expert implementation. While this solves the problem for all my components, the problem still exists where the Freescale provided components are using EnterCritical() and ExitCritical(): as these components are not open, I cannot change the sources of them. Until Freescale fixes that problem, I have it at least solved on my side. I plan to check the Processor Expert version number in my CriticalSection component, so I can revert back to a fixed Processor Expert implementation as needed.

❗ The Freescale provided Processor Expert SPI and UART drivers are still using the problematic versions of EnterCritical() and ExitCritical(). I need to see how I can deal with that situation.

I have updated the many example projects on my GitHub. If I missed something, simply post a comment ;-).

Happy Sectioning 🙂

9 thoughts on “CriticalSection Component

  1. Excellent article. I’m using Enter/ExitCritical to protect some atomic variables in a current engine ECU design. an Interrupt saves off some tick counts between external real world trigger pulses and then main line code (protected by Enter/ExitCritical) grabs a copy of the tick count for further processing.

    From my understanding of Enter/Exit Critical, I thought I was protected & I haven’t seen any issues yet, but I’m going to look further now as I see how this could easily corrupt my tick count.

    Like

  2. Hi Erich,
    When i set the rtos support enable in CS component, the ldd driver in PE can use taskEnterCritical() from freeRTOS automaticlly, but the high level driver components such as AsynchroSerial… still not using it taskEntercritical(), how we can set both high level component and LDD component using it ?

    Like

  3. Hi Erich
    I follow your post mostly for my KL25z.
    very good work it gives us direction thank you for such detailed posts

    I am facing while compiling this CS1 used in USB_MSD post of yours.
    it shows compile time error around this macro precisely the error looks something like this

    Invoking: Cross ARM C Compiler
    arm-none-eabi-gcc -mcpu=cortex-m0plus -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -g3 -I”C:\Program Files\eclipse\eclipse\ProcessorExpert/lib/Kinetis/pdd/inc” -I”C:\Program Files\eclipse\eclipse\ProcessorExpert/lib/Kinetis/iofiles” -I”C:/Freescale/workspace/PE_Blinky/Sources” -I”C:/Freescale/workspace/PE_Blinky/Generated_Code” -std=c99 -MMD -MP -MF”Generated_Code/CLS1.d” -MT”Generated_Code/CLS1.o” -c -o “Generated_Code/CLS1.o” “../Generated_Code/CLS1.c”
    ../Generated_Code/CLS1.c: In function ‘CLS1_ReadChar’:
    ../Generated_Code/CLS1.c:704:3: warning: implicit declaration of function ‘asm’ [-Wimplicit-function-declaration]
    CS1_EnterCriticalDrv();
    ^
    In file included from ../Generated_Code/CLS1.c:87:0:
    ../Generated_Code/CS1.h:81:5: error: expected ‘)’ before ‘:’ token
    : [output] “=m” (cpuSR) :: “r0″); \
    ^
    ../Generated_Code/CS1.h:58:3: note: in expansion of macro ‘CS1_EnterCritical’
    CS1_EnterCritical()

    Please let me know how to tackle this issue.

    Like

    • Hi Devidas,
      can you confirm that you have loaded my latest *.PEupd files from GitHub (see https://mcuoneclipse.com/2013/05/09/processor-expert-component-peupd-files-on-github/)? I ask as I have replaced asm() with __asm() as if you enable ‘strict’ ANSI options, then the compiler expects __asm.
      Otherwise, you should be able to change the compiler settings. In the project properties (C/C++ Build > Settings > Tool Settings > Cross ARM C Compiler > Optimization) set the language standard to ‘GNU ISO C90’ (toolchain default).
      I hope this helps?

      Like

      • hi Erich
        this is very good thing i experienced about this site
        thank you for such quick reply
        and by the way GNU ISO C90′ (toolchain default) did work with me
        and one good thing happen
        as I am exposed to this thing i researched bit about extended assembly
        so that is positive side of this
        Thanx again for this help

        Like

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.