1+ #if defined(GD32F20X) || defined(GD32F4XX)
2+ /* *
3+ * @file gd32_trng.h
4+ *
5+ */
6+ /* Copyright (C) 2026 by Arjan van Vught mailto:info@gd32-dmx.org
7+ *
8+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9+ * of this software and associated documentation files (the "Software"), to deal
10+ * in the Software without restriction, including without limitation the rights
11+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+ * copies of the Software, and to permit persons to whom the Software is
13+ * furnished to do so, subject to the following conditions:
14+
15+ * The above copyright notice and this permission notice shall be included in
16+ * all copies or substantial portions of the Software.
17+
18+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+ * THE SOFTWARE.
25+ */
26+
27+ #if defined(DEBUG_GD32_TRNG)
28+ #undef NDEBUG
29+ #endif
30+
31+ #include < cstdint>
32+ #include < cstdio>
33+
34+ #include " gd32_trng.h"
35+ #include " gd32.h" // IWYU pragma: keep
36+ #include " firmware/debug/debug_debug.h"
37+
38+ namespace gd32 ::trng {
39+ static constexpr uint32_t kTimeout = 0xFFFF ;
40+
41+ static bool ReadyCheck () {
42+ uint32_t timeout = 0 ;
43+ FlagStatus trng_flag = RESET ;
44+
45+ // check wherther the random data is valid
46+ do {
47+ timeout++;
48+ trng_flag = trng_flag_get (TRNG_FLAG_DRDY );
49+ } while ((RESET == trng_flag) && (kTimeout > timeout));
50+
51+ if (RESET == trng_flag) [[unlikely]] {
52+ // ready check timeout
53+ printf (" Error: TRNG can't ready \r\n " );
54+ trng_flag = trng_flag_get (TRNG_FLAG_CECS );
55+ printf (" Clock error current status: %d \r\n " , trng_flag);
56+ trng_flag = trng_flag_get (TRNG_FLAG_SECS );
57+ printf (" Seed error current status: %d \r\n " , trng_flag);
58+ return false ;
59+ }
60+
61+ return true ;
62+ }
63+
64+ bool Init () {
65+ DEBUG_ENTRY ();
66+
67+ // TRNG module clock enable
68+ rcu_periph_clock_enable (RCU_TRNG );
69+ // TRNG registers reset
70+ trng_deinit ();
71+ trng_enable ();
72+ // check TRNG work status
73+ const auto kReturn = ReadyCheck ();
74+
75+ DEBUG_PRINTF (" %s" , kReturn ? " Success" : " Error" );
76+ DEBUG_EXIT ();
77+ return kReturn ;
78+ }
79+
80+ static uint32_t out_last = 0 ;
81+
82+ bool Get (uint32_t & out) {
83+ if (ReadyCheck ()) {
84+ out = trng_get_true_random_data ();
85+ if (out != out_last) {
86+ out_last = out;
87+ return true ;
88+ }
89+ // the random data is invalid
90+ puts (" Error: Get the random data is same" );
91+ }
92+
93+ return false ;
94+ }
95+ } // namespace gd32::trng
96+
97+ #endif
0 commit comments