I've had a trawl around trying to find some 'locks' - a way of disabling interrupts on single thread embedded systems, and have only found the usual disable everything. Whereas the ARM blurb says that proirity level setting is a better way of doing this, so that you can restrict the disable to a narrower set of interrupts.

So here's my take :-
locks.h & locks.c

Code:


 

#ifndef LOCKS_H_
#define LOCKS_H_

#include 
#include 



#ifdef __cplusplus
extern "C"
{
#endif

    
// comment/uncomment as required 
#define USE_LOCKS


#if defined(USE_LOCKS)
    
//----------------------------------------------------------------------
// Simple lock/unlock mechanism for single thread systems, 
// to implement shared memory between program and ISR(s).
// The only way that a single thread program can be descheduled is by interrupts (ISRs),
// so the lock disables interrupts and the unlock re-enables them.
//    
// IMPORTANT - locks must be used as a pair around your shared data access code (can be nested)
//    
// Simply decide on the strategy you need for your system
// choose ONE :- 
// 1) ignore locks completely - comment out USE_LOCKS
// 2) LOCK_ALL - disable all interrupts 
// 3) LOCK_PRIORITY - disable interrupts based on priority level 
// 4) LOCK_GROUP - disable a specific group of interrupts 
// Note that you can still use NO_LOCKS with any of 2), 3) or 4) for different resources
// i.e. UART data - NO_LOCKS, PWM data - LOCK_PRIORITY ...
//
// each can be nested. 
// e.g. 4 nested locks will require 4 unlocks before interrupts are re-enabled
//----------------------------------------------------------------------
    
    
    
    
// ************* pick ONE ********************
//#define USE_LOCK_ALL
//#define USE_LOCK_PRIORITY
#define USE_LOCK_GROUP
    
        

typedef enum lockClassType NO_LOCKSLOCKS };


// available for direct access for all options

void lockAll(void);    //  no interrupts possible
void unLockAll(void); 


#if defined(USE_LOCK_ALL)

//----------------------------------------------------------------------
//  LOCK ALL
//----------------------------------------------------------------------
// ALL interrupts disabled 
//----------------------------------------------------------------------

typedef struct lockType {
    
enum lockClassType     lockClass;
};



#elif defined(USE_LOCK_PRIORITY)

    
//----------------------------------------------------------------------
//  LOCK PRIORITY
//----------------------------------------------------------------------
// interrupts are disabled based on their priority level 
// (which you must have previously setup - using setInterruptPriorityLevel() )
// there are 7 levels 1 .. 7 (for max 3 bits used)
// DONT USE : 0 = turn facility off - ALL interrupts ENABLED - this is the default
// i.e. will always return to 0 after equal number of call pairs
//
// 1 = highest priority mask = ALL interrupts disabled
// 2 = interrupts of priority 2..7 disabled, priority 1 interrupts enabled
// ...
// 7 = lowest priority mask = only interrupts of this priority are disabled, all others are enabled
//
// nesting -> lockPriority() can be called multiple times before calling equal number of unLockPriority()
// only successive higher priority masks are accepted :-
// e.g. 7, 4, 3, 1 ok     7, 4, 5, 3, 1  -> 5 ignored, continue with 4
// unLockPriority will reset to previous priority in list (like a stack)
//----------------------------------------------------------------------

boolean setInterruptPriorityLevel(UINT interruptIdBYTE priority);

typedef struct lockType {
    
enum lockClassType     lockClass;
    
UINT                priorityMask;
};

void lockPriority(UINT priorityMask); // returns previous priorityMask
void unLockPriority(void);


#elif defined(USE_LOCK_GROUP)

//----------------------------------------------------------------------
//  LOCK GROUP
//----------------------------------------------------------------------
// LOCK_GROUP allows a user subset of interrupts to be locked/unlocked e.g INT_GPIOA, INT_GPIOB ...
// LOCK_GROUP is more flexible than LOCK_PRIORITY, but will be slower.
// LOCK_GROUP only disables the interrupts you specify.
// interruptIds array MUST be terminated with NULL (0) - like a string.
//----------------------------------------------------------------------


typedef struct lockType {
    
enum lockClassType     lockClass;
    
BYTE                 *interruptIds;   // **** NULL (0) terminator  *****
};

void lockGroup(BYTE *interruptIds);    
void unLockGroup(BYTE *interruptIds);

#else

#error "Lock type not defined"

#endif // LOCK TYPE

//----------------------------------------------------------------------
//  LOCK wrapper
//----------------------------------------------------------------------
// general purpose wrapper of above functions :-
// getLockId() must be called once at initialisation/start to 
// obtain LOCK_ID to use with lock/unLock
//----------------------------------------------------------------------

typedef void *LOCK_ID

#define LOCK_ID_FAILED   0
LOCK_ID getLockId(struct lockType lockInfo); // call first to get LOCK_ID

LOCK_ID deleteLock(LOCK_ID lockId);

void lock(LOCK_ID lockId);  
void unLock(LOCK_ID lockId);

//utility
enum lockClassType getLockClass(LOCK_ID lockId);


#endif // USE_LOCKS

    
    
#ifdef __cplusplus
}
#endif


#endif // LOCKS_H_








Code:


 
#include 
#include 

#include 
#include 

#include 
#include 


#ifdef __cplusplus
extern "C"
{
#endif

    
    
#if defined(USE_LOCKS)


//----------------------------------------------------------------------
//  LOCK ALL
//----------------------------------------------------------------------

static UINT lockAllCount 0;  

// prevents the processor from responding to ALL interrupts
// no effect on NVIC (interrupt(s) will be waiting for the processor re-enable)
void lockAll(void) {    

    
__asm(  "    mov r0,         #1         n"
            "    msr PRIMASK,     r0        "
);        // disable all interrupts
    
lockAllCount++;
}

// Allows the processor to respond to interrupts 
void unLockAll(void) {
    
lockAllCount--;
    
    if (
lockAllCount == 0) {    
        
__asm(  "    mov r0,         #0         n"
                "    msr PRIMASK,     r0        "
);            // enable all interrupts        
    
}
}



#if defined(USE_LOCK_PRIORITY)

//----------------------------------------------------------------------
//  LOCK PRIORITY
//----------------------------------------------------------------------
// only 3 bits used by stellaris (bits 7..5)
// user values 1 .. 7  -> 1 = highest .. 7 = lowest priority

static const UINT priorityRegisterMap[15] =
{
    
0NVIC_SYS_PRI1NVIC_SYS_PRI2NVIC_SYS_PRI3NVIC_PRI0NVIC_PRI1,
    
NVIC_PRI2NVIC_PRI3NVIC_PRI4NVIC_PRI5NVIC_PRI6NVIC_PRI7,
    
NVIC_PRI8NVIC_PRI9NVIC_PRI10
};


// Sets the priority grouping of the interrupt controller to max number of priority levels.
// i.e. split between preemptable priority levels and subpriority levels  
// 3 bits available for hardware interrupt prioritization - so setup 3-5 split
// only used locally

void setMaxInterruptPriorityLevels(void) {
    
HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY NVIC_APINT_PRIGROUP_3_5;
}


// sets priority of an interrupt and sets max number of levels (i.e. 7)

boolean setInterruptPriorityLevel(UINT interruptIdBYTE priority) {
    
UINT priorityReg;
    
UINT value;
    
BYTE formattedPriority;
    
boolean setStatus FALSE;
    
    
setMaxInterruptPriorityLevels();
    
    if ((
interruptId >= 4) && (interruptId <>NUM_INTERRUPTS) &&
        (
priority && priority <>NUM_PRIORITY) ) {
        
        
formattedPriority priority <>NUM_PRIORITY_BITS);
        
        
priorityReg priorityRegisterMap[interruptId >> 2];
        
value HWREG(priorityReg);
        
value &= ~(0xFF <>* (interruptId 3)));
        
value |= formattedPriority <>* (interruptId 3));
        
HWREG(priorityReg) = value;
        
        
setStatus TRUE;
    }
    
    return 
setStatus;
}



#define PRIORITY_MASK_STACK_SIZE   16

BYTE priorityMaskStackPtr 0;
BYTE priorityMaskStack[PRIORITY_MASK_STACK_SIZE] = 
    { 
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,};


void lockPriority(UINT priorityMask) {    
    
    
__asm
            
"    push    {r1-r4}                            n"
            
            "    mov.w     r3,                r0                n"        
// priorityMask             
            
"    lsl.w     r3,    r3,            #5                n"        // <>
            
"    msr     BASEPRI_MAX,     r3                n"        // raise base priority (only higher priorities accepted)
                
            
"    ldr     r1,        =priorityMaskStackPtr    n"     
            "    ldrb    r3,     [r1]                    n"        
// priorityMaskStackPtr++
            
"    add        r3,        r3, #1                    n"                    
            "    strb    r3,        [r1]                    n"     
            
            "    mrs        r4,                BASEPRI            n"        
// readback    current priority
            
"    lsr.w     r4,    r4,            #5                n"        // >> 5
            
"    ldr        r2,     =priorityMaskStack        n"
            "    strb    r4,        [r2, r3]                n"     
// priorityMaskStack[priorityMaskStackPtr] = BASEPRI

            
"    pop        {r1-r4}                            n"
    
); 
}


void unLockPriority(void) {        
        
    
__asm(
            
"    push    {r1-r4}                                    n"
            
            "    ldr     r1,                =priorityMaskStackPtr    n"     
            "    ldr        r2,             =priorityMaskStack        n"
            "    ldrb    r3,             [r1]                    n"        
// priorityMaskStackPtr

//            "    mov     r4,                 #0                        n"
//            "    strb    r4,                [r2, r3]                n"     // clear current entry
            
            
"    sub        r3,                r3, #1                    n"        // priorityMaskStackPtr--            
            
"    strb    r3,                [r1]                    n"     
            "    ldrb    r4,                [r2, r3]                n"        
// priorityMaskStack[priorityMaskStackPtr]    
            
"    lsl     r4,    r4,            #5                        n"        // <>
            
"    msr     BASEPRI,         r4                        n"        // BASEPRI = priorityMaskStack[priorityMaskStackPtr]

            
"    pop        {r1-r4}                                    n"
    
);        
    
}


#elif defined(USE_LOCK_GROUP)


//----------------------------------------------------------------------
//  LOCK GROUP
//----------------------------------------------------------------------

#define USER_ISR_BASE_OFFSET         INT_GPIOA
#define USER_ISR_OFFSET_INTERVAL    32
#define USER_ISR_SECOND_OFFSET        ( USER_ISR_BASE_OFFSET + USER_ISR_OFFSET_INTERVAL )
#define MAX_NUM_USER_ISRS              ( NUM_INTERRUPTS - USER_ISR_BASE_OFFSET ) 
static BYTE ISRLockCounts[MAX_NUM_USER_ISRS];


void lockGroup(BYTE *interruptIds) {
    
BYTE offset;
    
    while (*
interruptIds != NULL) {
        
        if((*
interruptIds >= USER_ISR_BASE_OFFSET) && (*interruptIds <>USER_ISR_SECOND_OFFSET)) { 
            
offset = *interruptIds USER_ISR_BASE_OFFSET;
            
ISRLockCounts[offset]++;
            
// disable
            
HWREG(NVIC_DIS0) = <>offset;
        } else {
            if((*
interruptIds >= USER_ISR_SECOND_OFFSET) && (*interruptIds <>NUM_INTERRUPTS)) {
                
offset = *interruptIds USER_ISR_BASE_OFFSET;
                
ISRLockCounts[offset]++;
                
// disable
                
HWREG(NVIC_DIS1) = <>offset USER_ISR_OFFSET_INTERVAL);        
            }
        }    
        
        
interruptIds++;
        
    } 
// loop
}


void unLockGroup(BYTE *interruptIds) {
    
BYTE offset;

    while (*
interruptIds != NULL) {
        
        if((*
interruptIds >= USER_ISR_BASE_OFFSET) && (*interruptIds <>USER_ISR_SECOND_OFFSET)) { 
            
offset = *interruptIds USER_ISR_BASE_OFFSET;
            
ISRLockCounts[offset]--;
            if (
ISRLockCounts[offset] == 0) {
                
// enable
                
HWREG(NVIC_EN0) = <>offset;
            }
        } else {
            if((*
interruptIds >= USER_ISR_SECOND_OFFSET) && (*interruptIds <>NUM_INTERRUPTS)) {
                
offset = *interruptIds USER_ISR_BASE_OFFSET;
                
ISRLockCounts[offset]--;
                if (
ISRLockCounts[offset] == 0) {
                    
// enable
                    
HWREG(NVIC_EN1) = <>offset USER_ISR_OFFSET_INTERVAL);
                }
            }
        }    
        
        
interruptIds++;
            
    } 
// loop
}

#endif // LOCK TYPE

//----------------------------------------------------------------------
//  LOCK wrapper
//----------------------------------------------------------------------


#define PRIORITY_MASK_DISABLED    0


LOCK_ID getLockId(struct lockType lockInfo) {
    
    
boolean error FALSE;
    
    
struct lockType *lockId 
            (
struct lockType*)malloc(sizeof(struct lockType));
    
    if (
lockId != NULL) {
    
        
lockId->lockClass lockInfo.lockClass;
        
        switch (
lockInfo.lockClass) {
                
#if defined(USE_LOCK_ALL)
            
        
case NO_LOCKS :
        case 
LOCKS :
            break;
        
#elif defined(USE_LOCK_PRIORITY)
            
        
case NO_LOCKS :
            
lockId->priorityMask PRIORITY_MASK_DISABLED;
            break;
            
        case 
LOCKS :
            
            if ((
lockInfo.priorityMask PRIORITY_MASK_DISABLED) && 
                (
lockInfo.priorityMask <>NUM_PRIORITY)) {
                
                
lockId->priorityMask lockInfo.priorityMask;                
            } else {
                
error TRUE;
            }
            break;
        
#elif defined(USE_LOCK_GROUP)
            
        
case NO_LOCKS :
            
lockInfo.interruptIds NULL;
            break;
            
        case 
LOCKS :
                        
            if (
lockInfo.interruptIds != NULL) {
                
                
BYTE size strlen((char*)lockInfo.interruptIds) + 1;
                
lockId->interruptIds = (BYTE*)malloc(size);
                
                if (
lockId->interruptIds != NULL) {        
                    
memcpy(lockId->interruptIdslockInfo.interruptIdssize);            
                } else {
                    
error TRUE;
                }                
                
            } else {
                
error TRUE;
            }                
        
            break;
        
#endif // LOCK TYPE
            
            
break;
            
        default :
            
error TRUE;
            break;    
        } 
// switch        
        
        
if (error) {
            
lockId freeMemory(lockId); 
        }
    }    
    
    return 
lockId;
}


LOCK_ID deleteLock(LOCK_ID lockId) {
    
    
struct lockType *id = (struct lockType*)lockId;
    
    if (
id->lockClass == LOCKS) {
        
#if defined(USE_LOCK_GROUP)
        
id->interruptIds freeMemory(id->interruptIds);
#endif // LOCK TYPE
    
}
    
    
lockId freeMemory(lockId);
    
    return 
lockId;
}


void lock(LOCK_ID lockId) {
    
    
struct lockType *id = (struct lockType *)lockId;
        
    if (
id->lockClass == LOCKS) {
            
#if defined(USE_LOCK_ALL)
    
        
lockAll();
    
#elif defined(USE_LOCK_PRIORITY)
        
        
lockPriority(id->priorityMask);    
            
#elif defined(USE_LOCK_GROUP)
        
        
lockGroup(id->interruptIds);    
        
#endif // LOCK TYPE
        
    
}
}

void unLock(LOCK_ID lockId) {
    
    
struct lockType *id = (struct lockType *)lockId;

    if (
id->lockClass == LOCKS) {
            
#if defined(USE_LOCK_ALL)
    
        
unLockAll();
    
#elif defined(USE_LOCK_PRIORITY)
        
        
unLockPriority();    
        
#elif defined(USE_LOCK_GROUP)
        
        
unLockGroup(id->interruptIds);    
        
#endif // LOCK TYPE
        
    
}
}


//utility
enum lockClassType getLockClass(LOCK_ID lockId) {    
    
struct lockType *id = (struct lockType *)lockId;        
    return 
id->lockClass;     
}




#endif // USE_LOCKS




#ifdef __cplusplus
}
#endif










Feel free to improve/add/subtract and post bug fixes ...

You may need to use information from these links also :

systemRAM