Fix TRNG for NRF52

* When multiple TRNG objects are initialized, destroying the first
  object will turn the TRNG off for the other objects. This fix
  adds a counter to ensure that only when the last object is
  destroyed will it cause the TRNG to be disabled.

* The corner case where a user request 0 bytes is correctly handled
  and will now return immediately.
pull/6547/head
Marcus Chang 2018-02-17 21:20:06 -08:00
parent 5d5277336a
commit fa79e685fc
2 changed files with 58 additions and 23 deletions

View File

@ -37,21 +37,39 @@
*/ */
#if defined(DEVICE_TRNG) #if defined(DEVICE_TRNG)
#include "trng_api.h"
#include "hal/trng_api.h"
#include "hal/critical_section_api.h"
#include "nrf_drv_rng.h" #include "nrf_drv_rng.h"
/* Keep track of instantiated FlashIAP objects. */
static int nordic_trng_counter = 0;
void trng_init(trng_t *obj) void trng_init(trng_t *obj)
{ {
(void) obj; MBED_ASSERT(obj);
(void)nrf_drv_rng_init(NULL); /* Increment global counter. */
nordic_trng_counter++;
/* Initialize TRNG on first object only. */
if (nordic_trng_counter == 1) {
nrf_drv_rng_init(NULL);
}
} }
void trng_free(trng_t *obj) void trng_free(trng_t *obj)
{ {
(void) obj; MBED_ASSERT(obj);
nrf_drv_rng_uninit(); /* Decrement global counter. */
nordic_trng_counter--;
/* Deinitialize TRNG when all objects have been freed. */
if (nordic_trng_counter == 0) {
nrf_drv_rng_uninit();
}
} }
/* Get random data from NRF5x TRNG peripheral. /* Get random data from NRF5x TRNG peripheral.
@ -61,30 +79,45 @@ void trng_free(trng_t *obj)
*/ */
int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length) int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length)
{ {
uint8_t bytes_available; MBED_ASSERT(obj);
MBED_ASSERT(output);
MBED_ASSERT(output_length);
(void) obj; int result = 0;
nrf_drv_rng_bytes_available(&bytes_available); /* Return immediately if requested length is zero. */
if (length != 0) {
if (bytes_available == 0) { /* Query how many bytes are available. */
nrf_drv_rng_block_rand(output, 1); uint8_t bytes_available;
*output_length = 1; nrf_drv_rng_bytes_available(&bytes_available);
} else {
if (bytes_available > length) { /* If no bytes are cached, block until at least 1 byte is available. */
bytes_available = length; if (bytes_available == 0) {
} nrf_drv_rng_block_rand(output, 1);
*output_length = 1;
if (nrf_drv_rng_rand(output, bytes_available) != NRF_SUCCESS) {
*output_length = 0;
return -1;
} else { } else {
*output_length = bytes_available;
/* Get up to the requested number of bytes. */
if (bytes_available > length) {
bytes_available = length;
}
ret_code_t result = nrf_drv_rng_rand(output, bytes_available);
/* Set output length with available bytes. */
if (result == NRF_SUCCESS) {
*output_length = bytes_available;
} else {
*output_length = 0;
}
} }
/* Set return value based on how many bytes were read. */
result = (*output_length == 0) ? -1 : 0;
} }
return 0; return result;
} }
#endif #endif

View File

@ -3508,6 +3508,7 @@
"ITM", "ITM",
"TRNG", "TRNG",
"FLASH", "FLASH",
"TRNG",
"STCLK_OFF_DURING_SLEEP" "STCLK_OFF_DURING_SLEEP"
], ],
"extra_labels": [ "extra_labels": [
@ -3541,7 +3542,7 @@
"supported_form_factors": ["ARDUINO"], "supported_form_factors": ["ARDUINO"],
"inherits": ["MCU_NRF52832"], "inherits": ["MCU_NRF52832"],
"macros_add": ["BOARD_PCA10040", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_58", "NRF52_PAN_55", "NRF52_PAN_54", "NRF52_PAN_31", "NRF52_PAN_30", "NRF52_PAN_51", "NRF52_PAN_36", "NRF52_PAN_53", "S132", "CONFIG_GPIO_AS_PINRESET", "BLE_STACK_SUPPORT_REQD", "SWI_DISABLE0", "NRF52_PAN_20", "NRF52_PAN_64", "NRF52_PAN_62", "NRF52_PAN_63"], "macros_add": ["BOARD_PCA10040", "NRF52_PAN_12", "NRF52_PAN_15", "NRF52_PAN_58", "NRF52_PAN_55", "NRF52_PAN_54", "NRF52_PAN_31", "NRF52_PAN_30", "NRF52_PAN_51", "NRF52_PAN_36", "NRF52_PAN_53", "S132", "CONFIG_GPIO_AS_PINRESET", "BLE_STACK_SUPPORT_REQD", "SWI_DISABLE0", "NRF52_PAN_20", "NRF52_PAN_64", "NRF52_PAN_62", "NRF52_PAN_63"],
"device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "TRNG"], "device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"],
"release_versions": ["5"], "release_versions": ["5"],
"device_name": "nRF52832_xxAA" "device_name": "nRF52832_xxAA"
}, },
@ -3638,6 +3639,7 @@
"device_has": [ "device_has": [
"ITM", "ITM",
"FLASH", "FLASH",
"TRNG",
"STCLK_OFF_DURING_SLEEP" "STCLK_OFF_DURING_SLEEP"
], ],
"extra_labels": [ "extra_labels": [
@ -3671,7 +3673,7 @@
"supported_form_factors": ["ARDUINO"], "supported_form_factors": ["ARDUINO"],
"inherits": ["MCU_NRF52840"], "inherits": ["MCU_NRF52840"],
"macros_add": ["BOARD_PCA10056", "CONFIG_GPIO_AS_PINRESET", "SWI_DISABLE0", "NRF52_ERRATA_20"], "macros_add": ["BOARD_PCA10056", "CONFIG_GPIO_AS_PINRESET", "SWI_DISABLE0", "NRF52_ERRATA_20"],
"device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "TRNG"], "device_has_add": ["ANALOGIN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE"],
"release_versions": ["5"], "release_versions": ["5"],
"device_name": "nRF52840_xxAA", "device_name": "nRF52840_xxAA",
"bootloader_supported": true "bootloader_supported": true