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

nRF5340 NVS and readback_protection

Hi Everybody,

We found little or no literature about readback_protection on the nRF5340 SOC. Our issue is that for development and debugging it is not practical to use nrfjprog -recover in order to re-flash as that completely erases the storage partition too. What is the right way to retain NVS data?

Thank you.

Regards,

Milan 

Parents
  • Hi Milan,

    You can find documentation about access port protection in the CTRL-AP - Control access port chapter in the product specification.

    If I understand you correctly, then this question is about how you handle this during development. And in that case it typically does not make sense to prevent debugging, so then you simply disable access port protection. If you program an application that has been built without ENABLE_APPROTECT defined then you should be good to go (as nrfjprog --recover will have written to UICR.APPROTECT allready, and as long as you do not do a full chip erase or write more to that register, it retains its value and debugging will continue to be enabled as long as you do not program firmware built with ENABLE_APPROTECT defined.

  • Almost all clear.

    Except, it is still totally unclear how this is done in practice. There are mentions of using a 32-bit key (?) for both the 

    NRF_CTRLAP_S->APPROTECT.DISABLE register and the debugger. But again this is just speculation. Can you please point me to a guide how to disable this? And re-enable in case. 
  • Hi,

    That would work well.

    Have you been able to reproduce this (make it fail) with 1.7.0? I see you are using 1.7.99, which is master, and that changes more or less every day. That is not recommended for use unless you have a particular good reason for doing so.

  • Hi, I saw you created a sample app for zigbee and the nrf53. I will try that one. I changed to 1.7.0 and updated west. Its still the same. Will be back with some results on this. 

  • Hi Einar,

    Looks like I found the issue. This is all triggered by calling 

    wdt_setup(wdt, 0);
     .

    The WDT init function has no effect. The second I took the function out, the lock did not appear again. Do you have any workaround that?

  • That is surprising. Can you show a bit more of your code, ad least where "wdt" comes from? Is it the same if the second parameter is 1?

  • It is. That is why I did not think about it before. 

    Basically, 

    CONFIG_WATCHDOG=y
    The module for watchdog handling:
    LOG_MODULE_REGISTER(watchdog, LOG_LEVEL_INF);
    
    #if DT_NODE_HAS_STATUS(DT_ALIAS(watchdog0), okay)
    #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_watchdog)
    #define WDT_NODE DT_INST(0, nordic_nrf_watchdog)
    #endif
    /*
     * If the devicetree has a watchdog node, get its label property.
     */
    #ifdef WDT_NODE
    #define WDT_DEV_NAME DT_LABEL(WDT_NODE)
    #else
    #define WDT_DEV_NAME ""
    #error "Unsupported SoC and no watchdog0 alias in zephyr.dts"
    #endif
    
    const struct device *wdt; /*There could only be one watchdog instance for nRF*/
    
    static void wdt_callback(const struct device *wdt_dev, int channel_id)
    {
        static bool handled_event;
    
        if (handled_event)
        {
            return;
        }
    
        wdt_feed(wdt_dev, channel_id);
    
        LOG_ERR("Watchdog handled things..ready to reset");
        handled_event = true;
    }
    
    void dd_wdt_init()
    {
    
        LOG_WRN("Initialize Watchdog");
    
        wdt = device_get_binding(WDT_DEV_NAME);
        if (!wdt)
        {
            LOG_ERR("Cannot get WDT device");
            return;
        }
    }
    
    int dd_wdt_add_channel()
    {
        int wdt_channel_id;
        struct wdt_timeout_cfg wdt_config;
        /* Reset SoC when watchdog timer expires. */
        wdt_config.flags = WDT_FLAG_RESET_SOC;
        /* Expire watchdog after 1000 milliseconds. */
        wdt_config.window.min = 0U;
        wdt_config.window.max = WATCHDOG_TIMEOUT_MS;
    
        /* Set up watchdog callback. Jump into it when watchdog expired. */
        wdt_config.callback = wdt_callback;
    
        wdt_channel_id = wdt_install_timeout(wdt, &wdt_config);
        if (wdt_channel_id == -ENOTSUP)
        {
            wdt_config.callback = NULL;
            wdt_channel_id = wdt_install_timeout(wdt, &wdt_config);
        }
        if (wdt_channel_id < 0)
        {
            LOG_ERR("Watchdog channel install error");
            return -1;
        }
        LOG_WRN("Watchdog added to channel %i", wdt_channel_id);
    
        return wdt_channel_id;
    }
    
    int dd_watchdog_start()
    {
        int err = wdt_setup(wdt, 0);
        if (err < 0)
        {
            LOG_ERR("Watchdog setup error");
            return err;
        }
        return err;
    }
    
    void dd_wdt_feed(int wdt_channel_id)
    {
        wdt_feed(wdt, wdt_channel_id);
    }
    when dd_watchdog_start() is called (just a wrapper for wdt_setup()) the write protection kicks in. The program runs without errors and watchdog resets. 
Reply
  • It is. That is why I did not think about it before. 

    Basically, 

    CONFIG_WATCHDOG=y
    The module for watchdog handling:
    LOG_MODULE_REGISTER(watchdog, LOG_LEVEL_INF);
    
    #if DT_NODE_HAS_STATUS(DT_ALIAS(watchdog0), okay)
    #elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_watchdog)
    #define WDT_NODE DT_INST(0, nordic_nrf_watchdog)
    #endif
    /*
     * If the devicetree has a watchdog node, get its label property.
     */
    #ifdef WDT_NODE
    #define WDT_DEV_NAME DT_LABEL(WDT_NODE)
    #else
    #define WDT_DEV_NAME ""
    #error "Unsupported SoC and no watchdog0 alias in zephyr.dts"
    #endif
    
    const struct device *wdt; /*There could only be one watchdog instance for nRF*/
    
    static void wdt_callback(const struct device *wdt_dev, int channel_id)
    {
        static bool handled_event;
    
        if (handled_event)
        {
            return;
        }
    
        wdt_feed(wdt_dev, channel_id);
    
        LOG_ERR("Watchdog handled things..ready to reset");
        handled_event = true;
    }
    
    void dd_wdt_init()
    {
    
        LOG_WRN("Initialize Watchdog");
    
        wdt = device_get_binding(WDT_DEV_NAME);
        if (!wdt)
        {
            LOG_ERR("Cannot get WDT device");
            return;
        }
    }
    
    int dd_wdt_add_channel()
    {
        int wdt_channel_id;
        struct wdt_timeout_cfg wdt_config;
        /* Reset SoC when watchdog timer expires. */
        wdt_config.flags = WDT_FLAG_RESET_SOC;
        /* Expire watchdog after 1000 milliseconds. */
        wdt_config.window.min = 0U;
        wdt_config.window.max = WATCHDOG_TIMEOUT_MS;
    
        /* Set up watchdog callback. Jump into it when watchdog expired. */
        wdt_config.callback = wdt_callback;
    
        wdt_channel_id = wdt_install_timeout(wdt, &wdt_config);
        if (wdt_channel_id == -ENOTSUP)
        {
            wdt_config.callback = NULL;
            wdt_channel_id = wdt_install_timeout(wdt, &wdt_config);
        }
        if (wdt_channel_id < 0)
        {
            LOG_ERR("Watchdog channel install error");
            return -1;
        }
        LOG_WRN("Watchdog added to channel %i", wdt_channel_id);
    
        return wdt_channel_id;
    }
    
    int dd_watchdog_start()
    {
        int err = wdt_setup(wdt, 0);
        if (err < 0)
        {
            LOG_ERR("Watchdog setup error");
            return err;
        }
        return err;
    }
    
    void dd_wdt_feed(int wdt_channel_id)
    {
        wdt_feed(wdt, wdt_channel_id);
    }
    when dd_watchdog_start() is called (just a wrapper for wdt_setup()) the write protection kicks in. The program runs without errors and watchdog resets. 
Children
No Data
Related