-
Notifications
You must be signed in to change notification settings - Fork 3k
Update Nordic NRF52 based targets to SDK 14.2 #6547
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
Conversation
hal_critical_section_exit(); | ||
|
||
/* Deinitialize TRNG when all objects have been freed. */ | ||
if (counter == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has a race: Say thread A calls trng_free
and decreases nordig_trng_counter
to 0
, but gets interrupted before the branch condition counter == 0
is checked and nrf_drv_rng_uninit()
is called, and say at that point another thread B calls trng_init
, increasing nordig_trng_counter
to 1
and calling nrf_drv_rng_init
. Then, when thread A gets rescheduled, it calls nrf_drv_rng_uninit
, leaving B's TRNG context unusable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! Extending hal_critical_section_exit
to after both nrf_drv_rng_init
and nrf_drv_rng_uninit
should be sufficient, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marcuschangarm Yes I think that should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually we only need to synchronise nrf_drv_rng_uninit
with nordig_trng_counter
. But it would be more robust to do both.
} | ||
|
||
/* Set return value based on how many bytes was read. */ | ||
return (*output_length == 0) ? -1 : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the corner case where length == 0
, and where trng_get_bytes
should be a no-op, this would return failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! Thanks!
ARM Internal Ref: IOTSSL-2214 |
|
||
/* If no bytes are cached, block until at least 1 byte is available. */ | ||
if (bytes_available == 0) { | ||
nrf_drv_rng_block_rand(output, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This branch must not be taken if length == 0
. I suggest to check for length == 0
in the beginning and return immediately in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have reviewed trng_api.c
and made three requests to resolve a race condition and to correct the behaviour of trng_get_bytes
in the (useless but allowed) corner case where 0
bytes of entropy are requested.
*/ | ||
int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length) | ||
{ | ||
(void) obj; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trng_init
and trng_free
are synchronised but not this function. Please document if there are reasons to believe this is thread safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mbed HAL functions are not supposed to be thread safe - the caller is responsible for handling thread safety.
I'm not sure why trng_init
and trng_free
are safe - they should actually be non-safe to be consistent with the rest of the HAL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marcuschangarm Can the original author perhaps shed some light on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marcuschangarm These functions are called from feature/mbedtls
and not directly by the user. Mbed TLS calls these functions as abstract API and it does not know if a particular platform requires synchronisation. Hence, it is fine to provide some synchronisation here if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the thread safety be handled in Mbed TLS since that is the user facing API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't be using trng_get_bytes
before trng_init
is called and after trng_free
is called. Hence, there should just be one mutex for these three.
But since other platforms don't do that and Mbed TLS will not be calling it from multiple thread contexts I would say don't bother about threading now. We have to anyways revisit this once we know how it will be handled for all platforms via Mbed TLS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @mazimkhan for the info
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I'm a bit confused! 😄
Do you want me to:
- take out all thread safety that is currently there.
- insert thread safety everywhere.
I'm fine with either, but the current 2/3 thread safety looks weird.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also raised the point of 2/3 safety earlier. My opinion is to be consistent with other platforms that don't do any thread safety here. Hence, pt.1.
We will revisit thread safety later for all platforms and may introduce something similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good! I'll remove it completely then!
} | ||
} | ||
|
||
/* Set return value based on how many bytes was read. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo was -> were
|
||
/* If no bytes are cached, block until at least 1 byte is available. */ | ||
if (bytes_available == 0) { | ||
nrf_drv_rng_block_rand(output, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: Does this function performs a pop operation and clears the byte from the cache. So that same random number is not returned again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does.
bytes_available = length; | ||
} | ||
|
||
ret_code_t result = nrf_drv_rng_rand(output, bytes_available); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: Does this function performs a pop operation and clears the bytes from the cache. So that same random number is not returned again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does.
|
||
/* If no bytes are cached, block until at least 1 byte is available. */ | ||
if (bytes_available == 0) { | ||
nrf_drv_rng_block_rand(output, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is this optimum compared to blocking for requested length
bytes. Is it possible to state some typical time from the spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The typical time per byte is 120 microsecond, but there is no upper bound on per byte generation.
The 1 byte shortcut is to cater to a misinterpretation in the Cloud client on how the TRNG API should be used while still adhering to the TRNG API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one comment in the targets json file. HAL changes looks fine to me
"MBED_TICKLESS" | ||
], | ||
"device_has": [ | ||
"ANALOGIN", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are all these on new lines? this is not consistent with the rest of the file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- JSON is typically pretty printed with each element on a new line like this. This is a human readable file after all.
- It reduces merge conflicts when several people are adding and removing elements from the list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From consistency point of view, I would argue leave it as it is for the rest. Those 2 points are good though.
@theotherjimmy What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should change the style to this. It's always been a bit difficult to read these "device_has" lines like this.
@hanno-arm @mazimkhan Please take a look and see if this addresses your comments: cc59ae5 I'll squash the commit once it gets a thumbs up. |
"help": "UART DMA buffer. 2 buffers per instance. DMA buffer is filled by UARTE", | ||
"value": 8 | ||
} | ||
}, | ||
"target_overrides": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marcuschangarm What is the benefit of placing board specific target_overrides in the nordic library's mbed_lib.json.
From the viewpoint of designing a proprietary board using nrf52840 and custom_target.json:
Assuming mbed_lib.json files automatically overrule custom_target.json, would it not be preferable to make an mbed_lib.json for each target?
example:
mbed-os/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/mbed_lib.json
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question @loverdeg-ep
I am not certain if this change should be part of this PR. I would rather see it separately (needs also documentation where target configuration and why is it being the way it is).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't override configuration from one mbed_lib.json from another mbed_lib.json. All the settings in that file are related to configuring the HAL implementations, which is why I moved it out from targets.json.
There is a section in the README.md file about adding targets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marcuschangarm Based on @theotherjimmy's new config documentation.
The order in which overrides are considered is:
Libraries override target configuration with mbed_lib.json.
The application overrides target and library configuration with mbed_app.json
So you should be able to declare/define a config parameter in a targets.json and then override it with mbed_lib.json, or mbed_app.json as a last resort.
@vergil-SI and I have found that using custom_targets.json to override mbed_lib.json was a fruitless effort so we took the path of defining an mbed_lib.json for our custom target to override flow control set within "targets/TARGET_NORDIC/TARGET_NRF5x/mbed_lib.json"
Considering this, the approach we will take to implement custom board support is to have a repository containing the following:
PinNames.h
device.h
custom_target.json
mbed_lib.json
Though mbed-cli may not support custom_target.json not being in the root of a project, so we'll see.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies,
We used mbed_app.json to overcome uart-hwfc being defined in:
"mbed-os/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/TARGET_NRF52840_DK/mbed_lib.json"
If this proves to be the only solution then I'm not sure how we'll be able to make a portable and modular custom target BSP.
Will keep working at it but hoping @theotherjimmy or someone else can chime in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marcuschangarm @loverdeg-ep The only way I can think of to support custom BSPs is to move the hardware related configuration parameters to the target.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The thing is, that flag is a hack and not really related to the hardware.
In its original implementation, it would force all UART instances to use the RTC/CTS pins for flow control regardless whether the UART was used for STDIO or not. If you changed the interface firmware from DAPLINK to JLINK you would have to disable the flag since JLINK doesn't use flow control.
What we need is a flag in mbed_retarget.cpp to enable flow control explicitly for STDIO since that is where the STDIO instance is initialized from: https://github.com/ARMmbed/mbed-os/blob/master/platform/mbed_retarget.cpp#L148-L149
serial_init(&stdio_uart, tx, rx);
serial_baud(&stdio_uart, baud);
#if STDIO_FLOWCONTROL
serial_set_flow_control(&stdio_uart, FlowControlRTSCTS, rts, cts);
#endif
Details requests:
What is breaking here? Can this breaking change be part of another PR?
What new features does this PR bring? Is it related to the SDK update ? |
No, the changes are too fundamental to all the other work.
Plus loads of bug fixes and other stuff. |
/morph build |
Build : SUCCESSBuild number : 1699 Triggering tests/morph test |
Exporter Build : SUCCESSBuild number : 1333 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reviewed the change in trng_api.c
and it looks good to me.
Driver uses new API in SDK 14.2
Implement spi_api.c for NRF52X boards using SDK14. This driver does not implement SPI slave functions and does not use SPIM.
When possible, the I2C HAL will now use the TWI driver in SDK 14. The manual I2C API still maps onto the old TWI peripheral directly because the TWI driver doesn't provide the needed low-level functionality.
Added SPI and I2C section.
Serial implementation uses UARTE instead of UART peripheral: * EasyDMA is used for reading and writing data. * Triple buffering for receiving data. See README for full description.
serial_putc didn't work when called with interrupts disabled.
Instance counter keeps track of how many objects have been initialized and freed. On the first object the instance is enabled and on the last object the instance is disabled.
* Consolidated device_has and macros to the main MCU targets. * Moved errata configuration to mbed_lib.json for HAL implementation. * Moved clock configuration to mbed_lib.json for HAL implementation. * Moved UART configuration to mbed_lib.json for HAL implementation.
b964420
/morph build |
Rebased with flow control changes. Flow control is now off by default and can be configured from custom_target.json. |
Build : SUCCESSBuild number : 1807 Triggering tests/morph test |
Exporter Build : SUCCESSBuild number : 1455 |
Test : SUCCESSBuild number : 1616 |
Description
SDK updated to version 14.2 for all NRF52 based targets.
See https://os.mbed.com/forum/upcoming-features/topic/29477/ for a full list of changes.
See README.md for documentation of new features.
Note: this PR is step 1 in updating the NRF52 based boards. Next step is to remove old NRF52 code and SDK. Third step is to reorganize the NRF51 directory structure to fall in line with the new one.
Pull request type
[X] Fix
[ ] Refactor
[ ] New target
[X] Feature
[X] Breaking change