nrf_delay_us() and ble connection question

HI

softdvice : s132 

SDK version : nRF5_SDK_17.1.0_ddde560

I am using the nrf_delay_us() function.
The product I am using now controls the gpio in us units. Since it is a product that affects even 1us, I have the following question.
There is a problem with the nrf_delay_us() function intermittently delaying.
However, the problem seems to be a problem with the BLE connection status (connection interval). If I disconnect the BLE, the problem does not occur.
Could the nrf_delay_us() function be affected by the signal that periodically checks the connection? If so, is there a way to solve this problem?

BR

Cabin

Parents
  • Could the nrf_delay_us() function be affected by the signal that periodically checks the connection? If so, is there a way to solve this problem?

    This function is busy wait that just loops keeping the CPU busy and not allowing any lower or equal priority interrupt contexts to run until the delay is finished and the current running contexts exits.

    Having small  busy delays like this in micro seconds should be ok but should not use busy delays in higher priority interrupt contexts.

    Can you please tell me in which interrupt context you are using the nrf_delay_us()? Can you use a timer instead and sleep using sd_app_evt_wait()? after wakeup from this sleep in the timer event handler, you can do the same things that you do after nrf_delay_us, this way you can avoid the busy loop waiting.

  • HI

    The method I'm currently using is as follows:

    for(;;)
        {
            nrf_gpio_pin_write(EXIT_4,EXIT_4_DISABLE);
            nrf_delay_us(3);
            nrf_gpio_pin_write(EXIT_4,EXIT_4_ENABLE);
            nrf_delay_us(16);
        }
    In this situation, when I connect BLE, nrf_delay_us(3) sometimes gets delayed by 100us. I would like to know how to solve this problem.
Reply
  • HI

    The method I'm currently using is as follows:

    for(;;)
        {
            nrf_gpio_pin_write(EXIT_4,EXIT_4_DISABLE);
            nrf_delay_us(3);
            nrf_gpio_pin_write(EXIT_4,EXIT_4_ENABLE);
            nrf_delay_us(16);
        }
    In this situation, when I connect BLE, nrf_delay_us(3) sometimes gets delayed by 100us. I would like to know how to solve this problem.
Children
  • cabin said:
    In this situation, when I connect BLE, nrf_delay_us(3) sometimes gets delayed by 100us. I would like to know how to solve this problem.

    You cannot directly avoid that when BLE is enabled, then the softdevice (BLE controller) interrupts take the highest priority and will steal the CPU execution. The only two ways to avoid that is

    1. Disable BLE when you do not want unwanted delays injected into your application from BLE contexts.
    2. Use timeslots and get a timeslot approved for your application where it is guaranteed that during that timeslot BLE will not disturb your application by stealing away the CPU context.
  • Thank you for your reply.

    I have 3 questions.

    1. If so, can the nrf_delay_us() function be delayed due to ble?
    2. Is there an example code related to timeslots?

    3. Timeslots is a complex method. I only need the delay function. Is it possible to implement the delay function with the corresponding API?

  • cabin said:
    1. If so, can the nrf_delay_us() function be delayed due to ble?

    Yes, if the BLE timer interrupt or encryption interrupt happened in between the delay of nrf_delay_us, then the softdevice is going to take away the execution and make the nrf_delay_us look longer than desired.

    cabin said:
    2. Is there an example code related to timeslots?

    One of our senior engineer have created an external blog regarding usage of timeslots. It is a very nice guide on how to use it. I hope that you find it useful.

    cabin said:
    3. Timeslots is a complex method. I only need the delay function. Is it possible to implement the delay function with the corresponding API?

    Timeslots are indeed complex for simple solutions. But it is also the only guaranteed way to have uninterrupted execution of logic without BLE interruptions. If it is extremely critical that you delay functions needs to be precise alongside working with BLE, then timeslots are the only way. 

    Maybe you can explain me your exact usecase and why you need your delays to be so precise, and I can try to see if we can have any other alternative than timeslots.

  • We are developing a low-frequency treatment device.
    So we are controlling the low frequency with gpio to low and high.

    However, there is a big difference in the output depending on the interval between low and high.

    The delay we want is 10us, but due to ble, the delay is 100us, and the output is momentarily high.

  • You can configure a TIMER+GPIOTE+PPI to toggle the gpio without the use of CPU 

    You can use a PRESCALAR of 1 with TIMER1 (for example, do not use Timer0 when using BLE) and you then you can get one timer tick of 2us. If you put CC value as 5, then you will get a tick every 10us. Use the code something like this

    // Configure the GPIOTE output pin to toggle on a GPIOTE task
    NRF_GPIOTE->CONFIG[GPIOTE_CH_OUT] = GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos |
    GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos |
    16 /*LED4*/ << GPIOTE_CONFIG_PSEL_Pos |
    GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_MODE_Pos;
    
    // Configure Timer 0 to generate events every 10 microseconds
    NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;
    NRF_TIMER2->PRESCALER = 1;
    NRF_TIMER2->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << 0;
    NRF_TIMER2->MODE = TIMER_MODE_MODE_Counter << TIMER_MODE_MODE_Pos;
    
    // Set the counter limit to 10 microseconds
    NRF_TIMER2->CC[0] = 5; // This value might need to be adjusted based on the clock speed
    
    // Start the timer
    NRF_TIMER3->TASKS_START = 1;
    Now the pin will toggle irrespective of what BLE is doing.
Related