From 89e86fe6294948df0ca8aade93e9893f317dd5fc Mon Sep 17 00:00:00 2001 From: Alex Maestas Date: Sun, 17 Dec 2023 17:39:59 +0000 Subject: [PATCH] work around silicon erratum in TRNG --- movement/watch_faces/complication/randonaut_face.c | 2 +- movement/watch_faces/complication/toss_up_face.c | 3 ++- watch-library/hardware/watch/watch_private.c | 11 ++++++++++- watch-library/shared/watch/watch.h | 6 +++++- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/movement/watch_faces/complication/randonaut_face.c b/movement/watch_faces/complication/randonaut_face.c index bca334f..886aabb 100644 --- a/movement/watch_faces/complication/randonaut_face.c +++ b/movement/watch_faces/complication/randonaut_face.c @@ -357,7 +357,7 @@ static uint32_t _get_true_entropy(void) { while (!hri_trng_get_INTFLAG_reg(TRNG, TRNG_INTFLAG_DATARDY)); // Wait for TRNG data to be ready - hri_trng_clear_CTRLA_ENABLE_bit(TRNG); + watch_disable_TRNG(TRNG); hri_mclk_clear_APBCMASK_TRNG_bit(MCLK); return hri_trng_read_DATA_reg(TRNG); // Read a single 32-bit word from TRNG and return it #endif diff --git a/movement/watch_faces/complication/toss_up_face.c b/movement/watch_faces/complication/toss_up_face.c index 08dd005..dedc904 100644 --- a/movement/watch_faces/complication/toss_up_face.c +++ b/movement/watch_faces/complication/toss_up_face.c @@ -255,7 +255,8 @@ uint32_t get_true_entropy(void) { while (!hri_trng_get_INTFLAG_reg(TRNG, TRNG_INTFLAG_DATARDY)); // Wait for TRNG data to be ready - hri_trng_clear_CTRLA_ENABLE_bit(TRNG); + watch_disable_TRNG(TRNG); + hri_mclk_clear_APBCMASK_TRNG_bit(MCLK); return hri_trng_read_DATA_reg(TRNG); // Read a single 32-bit word from TRNG and return it #endif diff --git a/watch-library/hardware/watch/watch_private.c b/watch-library/hardware/watch/watch_private.c index cd607b8..4cae3cc 100644 --- a/watch-library/hardware/watch/watch_private.c +++ b/watch-library/hardware/watch/watch_private.c @@ -106,12 +106,21 @@ int getentropy(void *buf, size_t buflen) { } } - hri_trng_clear_CTRLA_ENABLE_bit(TRNG); + watch_disable_TRNG(TRNG); hri_mclk_clear_APBCMASK_TRNG_bit(MCLK); return 0; } +void watch_disable_TRNG(Trng *hw) { + hri_trng_clear_CTRLA_ENABLE_bit(hw); + // silicon erratum: the TRNG may leave internal components powered after disable. + // the workaround is to clear the register twice. + hri_trng_write_CTRLA_reg(hw, 0); + hri_trng_write_CTRLA_reg(hw, 0); +} + + void _watch_enable_tcc(void) { // clock TCC0 with the main clock (8 MHz) and enable the peripheral clock. hri_gclk_write_PCHCTRL_reg(GCLK, TCC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK0_Val | GCLK_PCHCTRL_CHEN); diff --git a/watch-library/shared/watch/watch.h b/watch-library/shared/watch/watch.h index 790f9a1..4043fdf 100644 --- a/watch-library/shared/watch/watch.h +++ b/watch-library/shared/watch/watch.h @@ -96,4 +96,8 @@ void watch_reset_to_bootloader(void); */ int read(int file, char *ptr, int len); -#endif /* WATCH_H_ */ \ No newline at end of file +/** @brief Disables the TRNG, working around a silicon erratum. + */ +void watch_disable_TRNG(Trng* hw); + +#endif /* WATCH_H_ */