]> git.earman.xyz Git - sensor-watch.git/commitdiff
work around silicon erratum in TRNG
authorAlex Maestas <git@se30.xyz>
Sun, 17 Dec 2023 17:39:59 +0000 (17:39 +0000)
committerAlex Maestas <git@se30.xyz>
Sun, 17 Dec 2023 17:39:59 +0000 (17:39 +0000)
movement/watch_faces/complication/randonaut_face.c
movement/watch_faces/complication/toss_up_face.c
watch-library/hardware/watch/watch_private.c
watch-library/shared/watch/watch.h

index bca334fb3a2b3fc12064bfc59d917bd86d8694ef..886aabb788bba2df3e1b7c490a87d0990e18126a 100644 (file)
@@ -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
index 08dd00522d6ddfffac3260fdfc16f2b10b4eb0c9..dedc904299646b20afa8396a0721cba22161b2e5 100644 (file)
@@ -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
index cd607b8e8529d82028471147d9ac8c4f7ab38a5b..4cae3ccbb06abd0d58bd71496265d8975e1dde8e 100644 (file)
@@ -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);
index 790f9a163d1c70fc0f1df3bec6076df335bd3c00..4043fdf7b93c843eec8eea48b0413ec7dd8e4175 100644 (file)
@@ -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_ */