Strange behavior when chainloading zephyr applications and using Kconfig CONFIG_UART_ASYNC_API=y

I am a student working on a project for university "forced" to do something unconventional:

I am currently writing a "custom first stage bootloader/updater" for a nrf54l15. This application is basically just reading a binary over a uart interface which uses the uart async api, writes the data to the memory and then juming to the entry point of the new application. To use the UART ASYNC API I have to set the Kconfig option CONFIG_UART_ASYNC_API=y
I tried several routines to jump to the new application but the following works:

void jmp_appl(void) {
    __disable_irq();
    void (*app_reset_handler)(void) = (void*) (*((volatile uint32_t *)(SLOT1_PARTITION_OFFSET + 4U )));
    SCB->VTOR = SLOT1_PARTITION_OFFSET;
    __set_MSP(*(volatile uint32_t *)SLOT1_PARTITION_OFFSET);
    __enable_irq();
    app_reset_handler();
}

Now here is the strange thing: after jumping to the reset handler of the new application the code is being executed at first but after executing uarte_nrfx_isr_int somehow ends up in an endless loop jumping between _isr_wrapper and z_arm_exc_exit

Hovever: this behavior doesn't show up when the Kconfig option CONFIG_UART_ASYNC_API=n is disabled.

My question is now Why does the secondary application doesn't boot up correctly when the Kconfig option is set?
My guess is that the DMA which is used for the uart async api (or the uart interrupts) probably causes these problems. However i didn't find a way to reset the peripherial to a state in which the problem doesn't occurs anymore.
This is actually not the first time facing problems with this API (my application ran into a hard fault when set up the callback for the API and simultaneously used spawning threads)

Parents
  • Hi,

    See the stuff we do in nrf_cleanup.c for MCUboot. Maybe you are missing some cleanup?

    Regards,
    Sigurd Hellesvik

  • Thanks for the fast help!!!

        nrfy_uarte_int_disable(NRF_UARTE20, 0xFFFFFFFF); // Or the used Uarte 
        nrfy_uarte_int_uninit(NRF_UARTE20);
        nrfy_uarte_task_trigger(NRF_UARTE20, NRF_UARTE_TASK_STOPRX);
    
        nrfy_uarte_event_clear(NRF_UARTE20, NRF_UARTE_EVENT_RXSTARTED);
        nrfy_uarte_event_clear(NRF_UARTE20, NRF_UARTE_EVENT_ENDRX);
        nrfy_uarte_event_clear(NRF_UARTE20, NRF_UARTE_EVENT_RXTO);
        nrfy_uarte_disable(NRF_UARTE20);
        
        // And any other cleanup code
        
        jmp_appl();

    Works perfectly fine! When CONFIG_UART_ASYNC_API is enabled.

    Is there no zephyr function for disabling the peripheral (setting it to a reset state) because it is just a such uncommon thing to do in a zephyr application (just asking out of curiosity)

  • zmnn said:
    Is there no zephyr function for disabling the peripheral (setting it to a reset state) because it is just a such uncommon thing to do in a zephyr application (just asking out of curiosity)

    Not a 100% certain answer, but:

    I don't know of any of the top of my head.

    And I would assume that we would have used such a function in the mcuboot cleanup if it existed.

Reply
  • zmnn said:
    Is there no zephyr function for disabling the peripheral (setting it to a reset state) because it is just a such uncommon thing to do in a zephyr application (just asking out of curiosity)

    Not a 100% certain answer, but:

    I don't know of any of the top of my head.

    And I would assume that we would have used such a function in the mcuboot cleanup if it existed.

Children
No Data
Related