NRF52840 DFU升级(四):GPREGRET标志位升级

参考博文《蓝牙nrf51822空中升级》

相关文章:《NRF52840 DFU升级(一): 按键升级》

                  《NRF52840 DFU升级(二):Hex文件打包》

                  《NRF52840 DFU升级(三) : Buttonless 升级》

 

前言

某些场合中,可能需要由应用程序通过按键或者协议指令等方式自动跳转到Bootloader当中,这种情况下我们并不需要使用Buttonless的方式去升级,因为已经有通讯接口可以传输控制指令,只需要写一个特定的标志位,然后复位设备,Bootloader启动时,读取该标志位判断是否停留在Bootloader当中。

如下NRF52840支持的升级方式如下:

分别为

1. APP不正确

2. 按键升级

3. PINRESET复位

4. GPREGRET标志位

5. BUTTONLESS

此处我们选择第四种方式标志位进入,适合已经有通讯接口的升级

static bool dfu_enter_check(void)
{
    if (!nrf_dfu_app_is_valid(crc_on_valid_app_required()))
    {
        NRF_LOG_DEBUG("DFU mode because app is not valid.");
        return true;
    }

    if (NRF_BL_DFU_ENTER_METHOD_BUTTON &&
       (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 0))
    {
        NRF_LOG_DEBUG("DFU mode requested via button.");
        return true;
    }

    if (NRF_BL_DFU_ENTER_METHOD_PINRESET &&
       (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk))
    {
        NRF_LOG_DEBUG("DFU mode requested via pin-reset.");
        return true;
    }

    if (NRF_BL_DFU_ENTER_METHOD_GPREGRET &&
       (nrf_power_gpregret_get() & BOOTLOADER_DFU_START))
    {
        NRF_LOG_DEBUG("DFU mode requested via GPREGRET.");
        return true;
    }

    if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS &&
       (s_dfu_settings.enter_buttonless_dfu == 1))
    {
        NRF_LOG_DEBUG("DFU mode requested via bootloader settings.");
        return true;
    }

    return false;
}

设置升级标志

GPREGRET是一个特殊寄存器,官方对该寄存器的解释如下:

简单来说GPREGRET这个寄存器在软复位的情况下自动保持,外部复位时才会清除。所以只需要先设置该寄出器的值,然后执行软复位,在Bootloader中检测该寄存器的值即可。

It's a RAM mapped retained register which will lose it's content after power-cycle, however it keeps its content after a wakeup from SYSTEMOFF mode. It's implemented like that in the softdevice so that you can easily use the individual bits.

the contents retained if enter sd_power_system_off()

An external reset will clear it.

 

可以参考Buttonless中处理的方式来做

uint32_t ble_dfu_buttonless_bootloader_start_finalize(void)
{
    uint32_t err_code;

    NRF_LOG_DEBUG("In ble_dfu_buttonless_bootloader_start_finalize\r\n");

    err_code = sd_power_gpregret_clr(0, 0xffffffff);
    VERIFY_SUCCESS(err_code);

    err_code = sd_power_gpregret_set(0, BOOTLOADER_DFU_START);
    VERIFY_SUCCESS(err_code);

    // Indicate that the Secure DFU bootloader will be entered
    m_dfu.evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER);

    // Signal that DFU mode is to be enter to the power management module
    nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);

    return NRF_SUCCESS;
}

简化后的代码为:

#include "nrf_soc.h"
#include "nrf_power.h"
...

void EnterDFU(void)
{
    #define BOOTLOADER_DFU_GPREGRET_MASK            (0xB0)      
    #define BOOTLOADER_DFU_START_BIT_MASK           (0x01)  
    #define BOOTLOADER_DFU_START    (BOOTLOADER_DFU_GPREGRET_MASK |         BOOTLOADER_DFU_START_BIT_MASK)      
    sd_power_gpregret_clr(0,0xffffffff);
    sd_power_gpregret_set(0, BOOTLOADER_DFU_START);
    nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);
}

特别注意:, 根据官方的答复,写GPREGRET寄存器之前,需要先Clear

 

 

 

 

你可能感兴趣的:(BLE)