This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Configure freeRTOS from SDK 17.0.2 to correctly call sd_nvic_critical_region_enter() rather than vPortEnterCritical() when using the softdevice s112

Hi...

I am using Nordic SDK V17.0.2 with a SoftDevice S112 and developing a project uses freeRTOS that came with this SDK

From reading the documentation about the soft device, I see that I should be using these APIs to enter/exit critical region of code

sd_nvic_critical_region_enter()

sd_nvic_critical_region_exit()

From what I can see, freeRTOS seems to be using entry/exit APIs that are NOT Softdevice aware

void vPortEnterCritical( void )
{
    portDISABLE_INTERRUPTS();
    uxCriticalNesting++;

    /* This is not the interrupt safe version of the enter critical function so
    assert() if it is being called from an interrupt context.  Only API
    functions that end in "FromISR" can be used in an interrupt.  Only assert if
    the critical nesting count is 1 to protect against recursive calls if the
    assert function also uses a critical section. */
    if ( uxCriticalNesting == 1 )
    {
        configASSERT( ( SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk ) == 0 );
    }
}

which is selected from the file  "nRF5_SDK\external\freertos\portable\CMSIS\nrf51\portmacro_cmsis.h"

#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()

these are used everywhere in freeRTOS  eg:  in queue.c

UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
{
UBaseType_t uxReturn;

	configASSERT( xQueue );

	taskENTER_CRITICAL();
	{
		uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting;
	}
	taskEXIT_CRITICAL();

	return uxReturn;
}

How do I get freeRTOS to use the softdevice aware entry/exit routines ?

sd_nvic_critical_region_enter()

sd_nvic_critical_region_exit()

Has some got or can give me these that are soft device aware calls

#define portSET_INTERRUPT_MASK_FROM_ISR() ???
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) ???
#define portDISABLE_INTERRUPTS()  ???
#define portENABLE_INTERRUPTS() ???
#define portENTER_CRITICAL() ???
#define portEXIT_CRITICAL() ???

maybe I have NOT configures the SDK correctly ??

   - can someone point me at where this setup is ??? 

Thanks

Ray

  • Hi Ray

    The portDISABLE_INTERRUPTS() call basically sets the BASEPRI register to block any interrupts below a certain priority. 

    The critical thing here is what interrupt level you set the limit to, which is defined by the configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY define in FreeRTOSConfig.h:

    /* The highest interrupt priority that can be used by any interrupt service
    routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
    INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
    PRIORITY THAN THIS! (higher priorities are lower numeric values. */
    #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY _PRIO_APP_HIGH

    In our implementation this is set to _PRIO_APP_HIGH, which corresponds to level 2, allowing all critical SoftDevice interrupts to be executed even in a critical section (interrupts level 0 and 1 are reserved for the SoftDevice to handle critical radio and timing related events). 

    In other words there is nothing else you need to do in order to make the FreeRTOS critical section SoftDevice aware. 

    Best regards
    Torbjørn

Related