Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

target/nrf91: add mass_erase and recovery probe #1785

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

maxd-nordic
Copy link

@maxd-nordic maxd-nordic commented Mar 15, 2024

Detailed description

  • add nrf91 rescue probe
  • add nrf91 mass erase
  • add detailed nrf91 identification
  • add nrf91 UICR writing
  • add UICR APPROTECT initialization
  • add UICR overwrite warning (recommend mass erase if value cannot be written)

Your checklist for this pull request

Closing issues

fixes #1778

@maxd-nordic
Copy link
Author

@dragonmux I added most of the missing parts for nrf91. Maybe you could give me pointers on how to handle the TODOs? The UICR APPROTECT part basically needs to do a flash write after each mass-erase to tell the "hardenend APPROTECT" system not to lock down the device after the next reset. This is also relevant for nRF53 support.

@dragonmux dragonmux added this to the v2.0 release milestone Mar 15, 2024
@dragonmux dragonmux added the Enhancement General project improvement label Mar 15, 2024
@dragonmux
Copy link
Member

The post-Flash write and mass-erase UICR fix-up sounds like something that should be a target exit_flash_mode function and then call that at the end of the nRF91 mass erase implementation too - that should take care of the problem.

Copy link
Member

@dragonmux dragonmux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done an initial review, there are a lot of interesting details here that we're very grateful to get to know about, like the TARGETID revision number being used for once in a part and having bearing on the part number.

Please don't forget to run clang-format on the contribution and fix the few hex constant capitalisation lints - the clang-format lint pass is currently broken but we are still enforcing it.

src/target/nrf91.c Outdated Show resolved Hide resolved
src/target/nrf91.c Outdated Show resolved Hide resolved
src/target/target_probe.h Outdated Show resolved Hide resolved
src/target/nrf91.c Outdated Show resolved Hide resolved
}

bool nrf91_probe(target_s *target)
{
adiv5_access_port_s *ap = cortex_ap(target);

if (ap->dp->version < 2U)
if (ap->dp->version < 2U || ap->dp->target_partno != 0x90U)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid a magic number here - 0x90U should ideally be #define'd above as, eg, ID_NRF91 so it's clearer what it is and where it comes from. Ideally a reference to the TRM section and page this information can be found from would be great, but we know that's not always possible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note that the choice of suggesting ID_NRF91 is for consistency with all the other target support implementations - while this is at least now a define that describes what the magic number is, it would be best to have it use the same style as the other target implementations.

src/target/nrf91.c Outdated Show resolved Hide resolved
src/target/nrf91.c Outdated Show resolved Hide resolved
src/target/nrf91.c Outdated Show resolved Hide resolved
src/target/nrf91.c Outdated Show resolved Hide resolved
@maxd-nordic
Copy link
Author

The post-Flash write and mass-erase UICR fix-up sounds like something that should be a target exit_flash_mode function and then call that at the end of the nRF91 mass erase implementation too - that should take care of the problem.

Thanks! Got it to work now. Just putting it in exit_flash_mode is enough IMO because a blank app will also cause the protection to engage.

@maxd-nordic maxd-nordic force-pushed the nrf91-recover branch 3 times, most recently from 2d81846 to b1391c6 Compare March 18, 2024 15:57
@dragonmux
Copy link
Member

The reason we said "and at the end of the mass erase function" is that it's up to the target support too override target->mass_erase with its own implementation (it's NULL by default) and the implementation will only do what you put in the function - so if you need to call target->exit_flash_mode then you'll need to include that in the implementation specifically. We'd be concerned for newly mass erased parts winding up protected without it.

@maxd-nordic
Copy link
Author

The reason we said "and at the end of the mass erase function" is that it's up to the target support too override target->mass_erase with its own implementation (it's NULL by default) and the implementation will only do what you put in the function - so if you need to call target->exit_flash_mode then you'll need to include that in the implementation specifically. We'd be concerned for newly mass erased parts winding up protected without it.

nrfjprog flashes a placeholder app onto the target when doing recovery. Should I include that here as well? (it would use up quite a bit of space) Just writing UICR is not enough to keep protection off. The way it's implemented now, you can do a mass-erase and UICR is written alongside your app.

@maxd-nordic
Copy link
Author

I got to check the flash write function again - we can skip the readynext wait if the page is erased beforehand.

@maxd-nordic
Copy link
Author

@dragonmux I managed to make the app image much smaller and include it here - the target is now unprotected after mass-erase. :)

@maxd-nordic
Copy link
Author

It might actually be better to implement target commands and show the CTRL-AP in any case. There is also a rarely-used feature that could lock mass-erase with a password.

Copy link
Member

@dragonmux dragonmux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies this PR got neglected and the code review we'd started some time back in March didn't get posted. If you could please rebase this PR on main and fix the lint pass issues along with this new review, that would be greatly appreciated as we would like to be able to land this before v2.0

0x5a, 0x02, 0xc3, 0xf8, 0x10, 0x2e, 0x03, 0x4b, 0x4f, 0xf0, 0x5a, 0x02,
0xc3, 0xf8, 0x00, 0x2e, 0xfe, 0xe7, 0x00, 0x00, 0x00, 0x90, 0x03, 0x50
};
unsigned int empty_app_len = 36;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use ARRAY_LENGTH() and make this a #define. This is not a constant expression in C and so uses Flash space unnecessarily to store a full variable. something like #define NRF91_EMPTY_APP_LEN ARRAY_LENGTH(empty_app) would be appropriate.

#define NRF91_UICR_APPROTECT_UNPROTECT_VAL 0x50FA50FAU
#define NRF91_UICR_ERASED_VAL 0xFFFFFFFFU

unsigned char empty_app[] = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not use raw types. uint8_t if you want to make this unsigned (and then U-suffix every value in the array initialisation so they're unsigned and won't get sign extended).

.apsel = 0x4U,
};

if (!nrf91_ctrl_ap_mass_erase(&ctrl_ap)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please drop these braces as they are unnecessary. The code base style is for single statement bodies of conditional block to not be enclosed in braces.

return false;

switch (ap->dp->target_partno) {
case 0x90:
#ifndef ENABLE_DEBUG
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wants to be #ifndef DEBUG_INFO_IS_NOOP to correctly guard these memory read-backs.

Comment on lines +27 to +28
#define NRF91_CTRL_IDR_EXPECTED 0x12880000
#define NRF91_AHB_AP_IDR_EXPECTED 0x84770001
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are missing their U suffixes to ensure they're defined as unsigned values. Because the AP IDR value (as an example) sets the sign bit on 32-bit platforms, if this value is then widened for any reason, then the upper bytes of the new value will be all set high, and if it is narrowed, this invokes UB (due to changing the value of the sign bit). Neither of these problems occur with unsigned constants.

Comment on lines +122 to +124
if (erase_needed) {
gdb_out("Skipping UICR erase, mass erase might be needed\n");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The braces are superfluous, please drop them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement General project improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

extending nRF91 support
2 participants