Skip to content

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

Merged
merged 39 commits into from
Apr 20, 2018
Merged

Update Nordic NRF52 based targets to SDK 14.2 #6547

merged 39 commits into from
Apr 20, 2018

Conversation

marcuschangarm
Copy link
Contributor

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

hal_critical_section_exit();

/* Deinitialize TRNG when all objects have been freed. */
if (counter == 0) {

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.

Copy link
Contributor Author

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?

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.

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;

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point! Thanks!

@ciarmcom
Copy link
Member

ciarmcom commented Apr 5, 2018

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

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.

Copy link

@hanno-becker hanno-becker left a 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;

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.

Copy link
Contributor Author

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.

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?

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.

Copy link
Contributor Author

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?

Copy link

@mazimkhan mazimkhan Apr 6, 2018

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.

Copy link
Contributor

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

Copy link
Contributor Author

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:

  1. take out all thread safety that is currently there.
  2. insert thread safety everywhere.

I'm fine with either, but the current 2/3 thread safety looks weird.

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.

Copy link
Contributor Author

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. */

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

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?

Copy link
Contributor Author

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

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?

Copy link
Contributor Author

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

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.

Copy link
Contributor Author

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.

Copy link
Contributor

@0xc0170 0xc0170 left a 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",
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor

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.

@marcuschangarm
Copy link
Contributor Author

@hanno-arm @mazimkhan

Please take a look and see if this addresses your comments: cc59ae5

@0xc0170

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": {
Copy link

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

Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link

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.

Copy link

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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

@0xc0170
Copy link
Contributor

0xc0170 commented Apr 9, 2018

Details requests:

[X] Breaking change

What is breaking here? Can this breaking change be part of another PR?

[X] Feature

What new features does this PR bring? Is it related to the SDK update ?

@marcuschangarm
Copy link
Contributor Author

What is breaking here?

  • I've removed several DEVICE_HAS flags because the hardware can't support it and the previous implementation was wrong.
  • The file structure has changed. If people included .h files with paths it might not work.
  • The SDK has changed. If people were relying on functionality directly from the SDK it might be gone.

Can this breaking change be part of another PR?

No, the changes are too fundamental to all the other work.

What new features does this PR bring? Is it related to the SDK update ?

  • You can add/remove SoftDevice on the fly.
  • Remove DEVICE_HAS items to save space.
  • The UART uses DMA and has a more flexible buffer management.
  • The NRF52840 gets a second UART.
  • The new SoftDevice provides BLE 5 features to the NRF52840.

Plus loads of bug fixes and other stuff.

0xc0170
0xc0170 previously approved these changes Apr 10, 2018
@0xc0170
Copy link
Contributor

0xc0170 commented Apr 10, 2018

/morph build

@mbed-ci
Copy link

mbed-ci commented Apr 10, 2018

Build : SUCCESS

Build number : 1699
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/6547/

Triggering tests

/morph test
/morph uvisor-test
/morph export-build
/morph mbed2-build

@mbed-ci
Copy link

mbed-ci commented Apr 10, 2018

Copy link

@hanno-becker hanno-becker left a 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.

Marcus Chang and others added 10 commits April 19, 2018 09:40
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.
@marcuschangarm marcuschangarm dismissed stale reviews from MarceloSalazar and 0xc0170 via b964420 April 19, 2018 16:44
@marcuschangarm
Copy link
Contributor Author

/morph build

@marcuschangarm
Copy link
Contributor Author

Rebased with flow control changes. Flow control is now off by default and can be configured from custom_target.json.

@mbed-ci
Copy link

mbed-ci commented Apr 19, 2018

Build : SUCCESS

Build number : 1807
Build artifacts/logs : http://mbed-os.s3-website-eu-west-1.amazonaws.com/?prefix=builds/6547/

Triggering tests

/morph test
/morph uvisor-test
/morph export-build
/morph mbed2-build

@mbed-ci
Copy link

mbed-ci commented Apr 19, 2018

@mbed-ci
Copy link

mbed-ci commented Apr 20, 2018

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

Successfully merging this pull request may close these issues.