Run a standard Zephyr application in NRF5

I have a sample application running in standard Zephyr 3.2.99. The application is just looping doing a sleep (k_sleep(K_SECONDS(10))) and logging a line.

I tried to build it to be run in nRF with MBR, Sofdevice (disabled) and bootloader. This will not be the system definitive app, just a special purpose one that would be convenient to be a Zephyr app.

To build it I took care of different memory layout: flash load offset 0x26000 (then changed to 0x1000), and reserving first 0x3000 RAM addresses that could be used by Softdevice.

When started by the Nordic bootloader, it correctly loops for >= 250 seconds (regardless of k_sleep interval, e.g. 10 or 30 sec), then it stops logging.

I tried doubling and quadrupling CONFIG_PRIVILEGED_STACK_SIZE and CONFIG_MAIN_STACK_SIZE (then even CONFIG_ISR_STACK_SIZE and CONFIG_IDLE_STACK_SIZE).
I checked usage of SVC interrupts, yet they seem unused bot in nFR and in zephyr. Then I investigated debugging, it looks like the last k_sleep call is waiting for a PendSV exception in arch_swap().

It's not clear to me why the PendSV interrupts are coming fro ~4 minutes and they stop. I read the S132 SoftDevice Specification and I couldn't find a valid reason why this should happen.

I thought about a possible incompatibility with Sofdtdevice and then I moved the app from 0x26000 to 0x1000 and I was surprised that the issue is the same.

The bootloader sets the vector table address for Sofdevice and now my app is in place of SD at 0x1000, so I would expect that the interrupts are forwarded (not only for 4 minutes).

Any suggestion is welcome.

Thanks,

Giancarlo.

  • I'm afraid we don't support running zephyr on the nRF5 SDK. Why are you not using the nRF Connect SDK for this application?

  • Hello !
    I'm Quentin, coworker on Giancarlo at Nexxiot.

    The context and reason why in this project we're not using the NRF connect SDK is explained here in this ticket :

      https://devzone.nordicsemi.com/support/298651 

    Basically, lots of legacy devices, we need to write a migration firmware to get away from proprietary legacy code.
    We're currently writing this migration firmware, and want to boot the Zephyr application through the proprietary bootloader (then erase everything and set the memory properly).

    The reason for the Zephyr application is because, well, the drivers are written for the Zephyr interface.

    I hope this gives more context!

    Best regards,

    Quentin

  • Hello. I did some further tests.

    First, as Vidar mentioned in Quentin's ticket 298651, I checked the VTOR register logging its value at application start.
    It has the correct application address, that is 0x26000 or 0x1000, depending on where I locate it. As expected, nothing changes re-writing it.

    Second, I would highlight the timings: the time when the k_sleep() call waits forever instead than 10 seconds happens after ~ 4 minutes (00:04:22 last log time). After that, the Zephyr timeout function sys_clock_announce() is called exactly every 4 minutes 16 seconds, that is half of the 24-bit timeout in nrf_rtc_timer: this is a good coincidence.
    I verified that the RTC interrupts happen as expected every ~ 8 minutes and 32 seconds.
    I'm trying to investigate what can happen differently (register values or whatever) when started by nRF5 bootloader instead of MCUboot.

    Perhaps you may have some advice.

  • Hello. Last week finally I found a solution that looks promising.
    The fix is at moment in my application init:
        /* Fix: Reset RTC1 bits resulting from nRF5 environment that prevent scheduling after ~ 4 minutes. */
        NRF_RTC1->INTENCLR = 0x00020000;
        NRF_RTC1->EVTENCLR = 0x00020002;
    I found this using a rough empirical approach: saving the processor registers values when the application is started with the working official Zephyr application and comparing them with the Zephyr application built for nRF5 SDK.
    After excluding non significant ones, the main difference was in
        INTENSET = INTENCLR = 0x00010002 -> 0x00030002
        EVTEN = EVTENSET = EVTENCLR = 0x00010000 -> 0x00030002
    it seems like the enable interrupt and event routing for COMPARE[1] is set in nRF5 environment in addition to the ones for COMPARE[0].
    I don't have the complete picture of the clock usage to understand why this produces the effects I saw. I'll try to have a look.
    Yet I'd like especially to look at the Zephyr initialization and why the results are different even when using CONFIG_INIT_ARCH_HW_AT_BOOT that I would have expected to fix my issue.
    I'm reporting these results, even in case you have useful suggestions.

  • Hello. I've proposed a fix in Zephyr init code in https://github.com/zephyrproject-rtos/zephyr/pull/55259

    Thank you for support.

    I closed the case by accident, indeed I would have waited the Zephyr PR above to be accepted first :-(

Related