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

GPREGRET/GPREGRET2 are bitmask registers?

We appear to have discovered today that if you do this sequence

sd_power_gpregret_clr(0xFF); sd_power_gpregret_set(0xA0); sd_power_gpregret_set(0x0B);

GPREGRET will contain 0xAB and not 0x0B.

Based on the way that BOOTLOADER_DFU_START is used in the SDK examples it never occurred to me that GPREGRET is a bitmask. I should have probably guessed that from the fact that there are _set() and _clr() functions but I thought they were provided for convenience in accessing the register.

Are GPREGRET (and the new GPREGRET2) treated as bitmaps? I can't find anything that explicitly says that in the SDK 11 source, SDK 11 documenation or the Reference Manuals for the nRF51 and nRF52.

The only hint appears to be the presence of the sd_power_gpregret_set() / sd_power_gpregret_get() API functions.

Cheers!

--- ta2

Parents
  • Here's something I just submitted as a support case (wasn't able to easily find where SDK suggestions/defects were to be officially submitted).

    this is to alert you to a liability in the example bootloader code in the SDK. Specifically, the bootloader_start() function within

    nRF5_SDK_11.0.0_89a8197.zip/libraries/bootloader/dfu/dfu_app_handler.c has the following code (line 140):

    err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START);

    When the bootloader gains control from bootloader_start(), it checks this value to determine whether the application initiated a DFU operation. If this value does not match, it assumes a boot from restart, initializes the soft device, and will wind up immediately calling back into the application. Whereupon the application reinitializes the soft device as if a reset had occurred and a hard fault results.

    Here's the problem: if any bit happens to be set in the GPREGRET register which is outside of the bit values of the BOOTLOADER_DFU_START value, then the above call will NOT result in GPREGRET having a value of BOOTLOADER_DFU_START--it will just set those bits along with whatever other bit(s) happen to already be set.

    This was happening in our application--where we use GPREGRET for other purposes prior to initiating switch to DFU from the app. The fix is pretty simple and much more robust:

    // Clear GPREGRET and set our exact DFU value.

    err_code = sd_power_gpregret_clr(0xffffffff);

    APP_ERROR_CHECK(err_code);

    err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START);

    APP_ERROR_CHECK(err_code);

    Perhaps it would be a good change to make in an upcoming SDK release as it would insulate the app-initiated DFU process from this potential glitch.

Reply
  • Here's something I just submitted as a support case (wasn't able to easily find where SDK suggestions/defects were to be officially submitted).

    this is to alert you to a liability in the example bootloader code in the SDK. Specifically, the bootloader_start() function within

    nRF5_SDK_11.0.0_89a8197.zip/libraries/bootloader/dfu/dfu_app_handler.c has the following code (line 140):

    err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START);

    When the bootloader gains control from bootloader_start(), it checks this value to determine whether the application initiated a DFU operation. If this value does not match, it assumes a boot from restart, initializes the soft device, and will wind up immediately calling back into the application. Whereupon the application reinitializes the soft device as if a reset had occurred and a hard fault results.

    Here's the problem: if any bit happens to be set in the GPREGRET register which is outside of the bit values of the BOOTLOADER_DFU_START value, then the above call will NOT result in GPREGRET having a value of BOOTLOADER_DFU_START--it will just set those bits along with whatever other bit(s) happen to already be set.

    This was happening in our application--where we use GPREGRET for other purposes prior to initiating switch to DFU from the app. The fix is pretty simple and much more robust:

    // Clear GPREGRET and set our exact DFU value.

    err_code = sd_power_gpregret_clr(0xffffffff);

    APP_ERROR_CHECK(err_code);

    err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START);

    APP_ERROR_CHECK(err_code);

    Perhaps it would be a good change to make in an upcoming SDK release as it would insulate the app-initiated DFU process from this potential glitch.

Children
No Data
Related