7
31
Fork
You've already forked blackmagic
23

target/nrf91: add mass_erase and recovery probe #1785

Open
maxd-nordic wants to merge 1 commit from maxd-nordic/nrf91-recover into main
pull from: maxd-nordic/nrf91-recover
merge into: blackmagic-debug:main
blackmagic-debug:main
blackmagic-debug:feature/bmda-remote-comms
blackmagic-debug:ALTracer/feature/aarch64-ident
blackmagic-debug:feature/better-meson-optimisation-handling
blackmagic-debug:feature/am335x-support
blackmagic-debug:feature/esp32-c3-support
blackmagic-debug:feature/cortex-ar-software-breakpoints
blackmagic-debug:feature/unit-testing
blackmagic-debug:feature/windows-usb-serial-interface-naming
blackmagic-debug:fix/bmp-external-spi
blackmagic-debug:ALTracer/feature/bluepillplus-platform
blackmagic-debug:ALTracer/feature/at32f43x-unrdp
blackmagic-debug:feature/const-correctness
blackmagic-debug:ALTracer/feature/fault_handlers
blackmagic-debug:ALTracer/feature/hazard3-ice40-support
blackmagic-debug:fix/ci-cleanup
blackmagic-debug:ALTracer/fix/gdb-10-12-thread
blackmagic-debug:ALTracer/feature/blackpill-f4-adc
blackmagic-debug:ALTracer/fix/cortex-desc-allocfail-report
blackmagic-debug:ALTracer/feature/spi-perf
blackmagic-debug:ALTracer/feature/calibrate_swd
blackmagic-debug:ALTracer/feature/blank-check
blackmagic-debug:feature/avr
blackmagic-debug:v2.0
blackmagic-debug:v1.9
blackmagic-debug:v1.10
blackmagic-debug:v1.8
maxd-nordic commented 2024年03月15日 13:17:31 +01:00 (Migrated from github.com)
Copy link

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

<!-- Filling this template is mandatory --> ## 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 * [x] I've read the [Code of Conduct](https://github.com/blackmagic-debug/blackmagic/blob/main/CODE_OF_CONDUCT.md) * [x] I've read the [guidelines for contributing](https://github.com/blackmagic-debug/blackmagic/blob/main/CONTRIBUTING.md) to this repository * [x] It builds for hardware native (see [Building the firmware](https://github.com/blackmagic-debug/blackmagic?tab=readme-ov-file#building-black-magic-debug-firmware)) * [x] It builds as BMDA (see [Building the BMDA](https://github.com/blackmagic-debug/blackmagic?tab=readme-ov-file#building-black-magic-debug-app)) * [x] I've tested it to the best of my ability * [x] My commit messages provide a useful short description of what the commits do ## Closing issues <!-- put "fixes #XXXX" here to auto-close the issue(s) that your PR fixes (if any). --> fixes #1778
maxd-nordic commented 2024年03月15日 13:21:22 +01:00 (Migrated from github.com)
Copy link

@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 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.

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.

The post-Flash write and mass-erase UICR fix-up sounds like something that should be a target [`exit_flash_mode`](https://github.com/blackmagic-debug/blackmagic/blob/fa79ab6b8bba4f9807354e48fca477fc565854e8/src/target/target_internal.h#L141) function and then call that at the end of the nRF91 mass erase implementation too - that should take care of the problem.
dragonmux left a comment
Copy link

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.

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.
@ -12,1 +13,4 @@
#define NRF91_NVMC_ERASEALL (NRF91_NVMC + 0x50cU)
#define NVMC_TIMEOUT_MS 300U

Please prefix these with NRF91_ to maintain the macro prefixing for the file.

Please prefix these with `NRF91_` to maintain the macro prefixing for the file.

This uses int for a boolean return value, please use bool instead. We're in C11 here, so <stdbool.h> functions properly, giving access to clean error returns. Note, we would strongly prefer true to mean success otherwise the caller side logic becomes cumbersome and difficult to comprehend, which is error-prone.

This uses `int` for a boolean return value, please use `bool` instead. We're in C11 here, so `<stdbool.h>` functions properly, giving access to clean error returns. Note, we would strongly prefer `true` to mean success otherwise the caller side logic becomes cumbersome and difficult to comprehend, which is error-prone.

Please use PRIx32 for the format specifier, not x, as idr is a uint32_t and so this doesn't work on Xtensa or several desktop platforms.

eg: DEBUG_ERROR("nRF91: AHB-AP IDR is 0x%08" PRIx32 ", expected 0x84770001\n", ahb_ap.idr);

It would also be better for Flash space if the expected value were formatted in the same way.

Please use `PRIx32` for the format specifier, not `x`, as idr is a `uint32_t` and so this doesn't work on Xtensa or several desktop platforms. eg: `DEBUG_ERROR("nRF91: AHB-AP IDR is 0x%08" PRIx32 ", expected 0x84770001\n", ahb_ap.idr);` It would also be better for Flash space if the expected value were formatted in the same way.

This would be fine as a DEBUG_* statement, but should be avoided in the scan output as it's not guaranteed where exactly this will end up in the information display, while also duplicating the information to the user from the target->driver strings.

Same comment as below on uint32_t needing PRIx32.

This would be fine as a DEBUG_* statement, but should be avoided in the scan output as it's not guaranteed where exactly this will end up in the information display, while also duplicating the information to the user from the target->driver strings. Same comment as below on uint32_t needing PRIx32.

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.

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.

Please avoid single letter variable naming for this, please use target instead. Likewise for nrf91_rescue_probe() on return from target_new().

This is the style we've been gradually moving the whole code base to.

Please avoid single letter variable naming for this, please use `target` instead. Likewise for `nrf91_rescue_probe()` on return from `target_new()`. This is the style we've been gradually moving the whole code base to.

This can be made const, so lets do so.

This can be made `const`, so lets do so.
@ -98,5 +98,6 @@ bool stm32mp15_cm4_probe(target_s *target);
bool zynq7_probe(target_s *target);

const here will be ignored by the compiler. This should be a clang-tidy lint. Having it in the function definitions is correct though.

`const` here will be ignored by the compiler. This should be a `clang-tidy` lint. Having it in the function definitions is correct though.

Easiest way to fix this would be to gdb_outf() a message like "Skipping UICR erase, operation requires mass erase". If there's a good way to blank check the UICR that can be used to have this routine return true with no message, and then return false if the UICR is not blank.

Easiest way to fix this would be to `gdb_outf()` a message like "Skipping UICR erase, operation requires mass erase". If there's a good way to blank check the UICR that can be used to have this routine `return true` with no message, and then `return false` if the UICR is not blank.
maxd-nordic commented 2024年03月18日 11:17:00 +01:00 (Migrated from github.com)
Copy link

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.

> The post-Flash write and mass-erase UICR fix-up sounds like something that should be a target [`exit_flash_mode`](https://github.com/blackmagic-debug/blackmagic/blob/fa79ab6b8bba4f9807354e48fca477fc565854e8/src/target/target_internal.h#L141) 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.

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.

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 commented 2024年03月19日 10:55:53 +01:00 (Migrated from github.com)
Copy link

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.

> 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 commented 2024年03月19日 12:55:01 +01:00 (Migrated from github.com)
Copy link

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

I got to check the flash write function again - we can skip the readynext wait if the page is erased beforehand.
maxd-nordic commented 2024年03月22日 15:21:34 +01:00 (Migrated from github.com)
Copy link

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

@dragonmux I managed to make the app image much smaller and include it here - the target is now unprotected after mass-erase. :)
maxd-nordic commented 2024年03月25日 16:52:53 +01:00 (Migrated from github.com)
Copy link

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.

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.
dragonmux left a comment
Copy link

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

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
@ -18,3 +74,4 @@
static bool nrf91_wait_ready(target_s *const target, platform_timeout_s *const timeout)
{
/* Poll for NVMC_READY */

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.

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.

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).

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).
@ -49,6 +106,25 @@ static bool nrf91_flash_erase(target_flash_s *flash, target_addr_t addr, size_t
return nrf91_wait_ready(target, NULL);

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.

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.
@ -104,0 +311,4 @@
}
bool nrf91_rescue_probe(adiv5_access_port_s *ap)
{

The braces are superfluous, please drop them.

The braces are superfluous, please drop them.

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.

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.

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

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

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.

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.
This pull request has changes conflicting with the target branch.
  • src/target/adiv5.c
  • src/target/adiv5.h
  • src/target/nrf91.c
  • src/target/target_probe.c
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin maxd-nordic/nrf91-recover:maxd-nordic/nrf91-recover
git switch maxd-nordic/nrf91-recover
Sign in to join this conversation.
No reviewers
Labels
Clear labels
BMD App
Black Magic Debug App (aka. PC hosted) (not firmware)
BMP Firmware
Black Magic Probe Firmware (not PC hosted software)
Bug
Confirmed bug
Build system
Build system
Can't reproduce
Maintainers can't reproduce this problem
CI
Continuous Integration System
Contribution wanted
User contributions welcome
Documentation
Project documentation
Draft
Work in progress draft
Duplicate
This issue or pull request already exists
Enhancement
General project improvement
Feedback wanted
Requires additional submitter feedback
Foreign Host Board
Non Native hardware to runing Black Magic firmware on
GDB
Issue/PR related to GDB
Good first issue
Good for newcommers
HwIssue Mitigation
Solving or mitigating a Hardware issue in Software
Information Needed
Maintainers need more information
NativeHardware
Official Black Magic Debug Hardware
New Host Board
New hardware to run Black Magic firmware on
New Target
New debug target
Off Topic
Something that does not involve the project in any way
Potential Bug
A potential, unconfirmed or very special circumstance bug
Regression
Bug caused by a regression
User Interest Needed
More user interest required before consideration
User Testing Needed
Looking for user testing reports
Won't fix
Outside of the project scope or works as intended
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
blackmagic-debug/blackmagic!1785
Reference in a new issue
blackmagic-debug/blackmagic
No description provided.
Delete branch "maxd-nordic/nrf91-recover"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?