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

CRITICAL_REGION_EXIT with Timer and UART interrupts

Hi All,

I have some code that I'm porting from a Zilog platform over to the nRF52 platform.  The code uses 1 timer and 1 uart.  The goal of the code is to handle RS485 messages.

First, a quick question on the timer, I'm using the following function:

nrf_drv_timer_extended_compare(&TIMER_MB, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

This is from the timer example.  Am I correct that this timer will continue to call interrupts at the specified rate until I specifically call nrf_drv_timer_disable?   

Second part of the question, is I'm using the following to setup a UART:

APP_UART_FIFO_INIT(&comm_params, UART_RX_BUF_SIZE, UART_TX_BUF_SIZE, uart_error_handle, APP_IRQ_PRIORITY_LOWEST, err_code);

(I've run the example and had everything running with putty, a windows serial program using rs232 protocol.)

For my RS485 app I need to toggle when the device can read and when it transmit.  What I'm currently doing is app_uart_close(),  and then redefine the port in the desired mode.

My real question is, I perform "CRITICAL_REGION_ENTER() "  when making changes to the UART and after everything is setup I perform "CRITICAL_REGION_EXIT()"

my problem is for some reason it is triggering a NRF_BREAKPOINT_COND    at CRITICAL_REGION_EXIT() when stepping through in debug mode.  (I'm running in SEGGER Embedded Studio.)

Any thoughts?  Should I be using different functions to toggle the UART setup?

thanks!

Bob

  • CRITICAL_REGION_ENTER() is defined in app_util_platform.h like this:

    #ifdef SOFTDEVICE_PRESENT
    #define CRITICAL_REGION_ENTER() \
    { \
    uint8_t __CR_NESTED = 0; \
    app_util_critical_region_enter(&__CR_NESTED);
    #else
    #define CRITICAL_REGION_ENTER() app_util_critical_region_enter(NULL)
    #endif

    app_util_critical_region_enter() is defined in app_util_platformc. like this:

    void app_util_critical_region_enter(uint8_t *p_nested)
    {
    #if __CORTEX_M == (0x04U)
    ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get())
    #endif

    #if defined(SOFTDEVICE_PRESENT)
    /* return value can be safely ignored */
    (void) sd_nvic_critical_region_enter(p_nested);
    #else
    app_util_disable_irq();
    #endif
    }

    Note the ASSERT() that checks the current privilege level.

    The ARM Cortex-M4 supports a couple of different execution states:

    - handler mode (you're executing in an exception handler/interrupt service routine)

    - thread mode (you're *not* executing in an exception handler)

    Also, thread mode has two execution modes: privileged and unprivileged. (Handler mode is always privileged.) You can control the privilege state by setting a bit in the CONTROL register. If you have an RTOS, it's permitted to have some threads run in privileged state and others in unprivileged state. The unprivileged ones will not be able to affect critical system state. The system control block, NVIC and a few other things will be off limits. (You also can't change the CONTROL register from unprivileged state, so if you make yourself unprivileged, the only way to change back is through an exception handler.)

    Critical regions are guarded by enabling/disabling interrupts using the "cpsid i" instruction. This is a privileged instruction. If you use it from thread mode in the unprivileged state, it has no effect (it becomes a no-op). The ASSERT above is intended to trap cases where people are tying to use this mechanism from an unprivileged state since obviously it won't work, and this would thwart your attempt to guard a critical section.

    Lastly, if the ASSERT() fails, it will execute a breakpoint trap instruction.

    The implication here is that somehow you've set up your system so that your application code is executing in unprivileged thread mode, and you're getting an ASSERT() that's trying to tell you you're attempting to perform a privileged operation. I'm not sure how things ended up this way since I don't think the nRF52 SDK tries to use unprivileged thread mode.

    -Bill

  • How do I force my application to run in Privileged mode (even while debugging)?

    Curious thing is this isn't the first time it enters and exists the CRITICAL_REGION.  It does so earlier in the code but the UART isn't running at that moment, only the timer.

    thanks,

    Bob

  • It's supposed to be running in privileged mode by default. That why I said "I'm not sure how things ended up this way."

    Check the stack trace where the breakpoint happens and see how you got there. Also, dump the registers with the debugger and look at the CONTROL register. If bit 0 is set, that means unprivileged thread mode is enabled. If it's clear, then you're running in privileged mode. If you are running in privileged mode them maybe the problem is something else and I guessed wrong.

    -Bill

  • Ok, let me track down the CONTROL register in the SEGGER debugger

    Would it happen to be apsr->C or xpsr->C    (my limited knowledge of Assembly makes me think that is the carry flags.)

    thanks, I'll go hunting in the AM

    Bob

  • The 'psr' here means the program status register. This register looks a little different depending on whether you're in handler or thread mode. I think you're right that this just the carry flag.

    This part of the CPU behavior is part of the Cortex-M4 design, which is from ARM, not Nordic. This manual provides a good overview:

    http://infocenter.arm.com/help/topic/com.arm.doc.dui0553b/DUI0553.pdf

    I think you want the 'cfbp' display. From what I can find, this stands for Control/Fault/Basepri/Primask. These are all CPU state registers. (See section 2.1.3 in the above document.) I think you need to click the arrow to expand this to get the whole picture. The value 0x00000001 is a little confusing since I don't know exactly which register it's referring to.

    (Disclaimer: I use GDB for debugging, which always displays these registers just by saying "info registers.")

    -Bill

Related