Skip to content

Commit 46d8ac7

Browse files
committed
Add GD32 TRNG support and code cleanups
Introduces a new `gd32::trng` interface and implementation for GD32F20X/GD32F4XX, including initialization, readiness checks, timeout/error reporting, and random value retrieval with duplicate-value detection. Also refactors `board::SysName()` to return a shared static constant with computed length, and applies small `delayus.cpp` maintenance updates for include/lint handling and loop style consistency.
1 parent e8c95f9 commit 46d8ac7

4 files changed

Lines changed: 143 additions & 4 deletions

File tree

lib-gd32/include/gd32_trng.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* @file gd32_trng.h
3+
*
4+
*/
5+
/* Copyright (C) 2026 by Arjan van Vught mailto:info@gd32-dmx.org
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
26+
#ifndef GD32_TRNG_H_
27+
#define GD32_TRNG_H_
28+
29+
#if defined(GD32F10X) || defined(GD32F30X)
30+
#errror MCU is not supported
31+
#endif
32+
33+
#include <cstdint>
34+
35+
namespace gd32::trng {
36+
bool Init();
37+
bool Get(uint32_t& out);
38+
} // namespace gd32::trng
39+
40+
#endif // GD32_TRNG_H_

lib-gd32/src/board.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace board {
2929
static constexpr float kCoreTemperatureMin = -40.0;
3030
static constexpr float kCoreTemperatureMax = +85.0;
3131
static constexpr const char kWebsite[] = "https://gd32-dmx.org";
32+
static constexpr char kSysName[] = "Embedded";
3233

3334
const char* Website() {
3435
return kWebsite;
@@ -57,7 +58,7 @@ const char* CpuName(uint8_t& length) {
5758
}
5859

5960
const char* SysName(uint8_t& length) {
60-
length = 8;
61-
return "Embedded";
61+
length = sizeof(kSysName) - 1U;
62+
return kSysName;
6263
}
6364
} // namespace board

lib-gd32/src/delayus.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#include <cstdint>
3434
#include <cassert>
3535

36-
#include "gd32.h"
36+
#include "gd32.h" // IWYU pragma: keep
3737

3838
static constexpr auto kTicksPerUs = (MCU_CLOCK_FREQ / 1000000U);
3939

@@ -46,6 +46,7 @@ void UdelayInit() {
4646
}
4747

4848
namespace timing {
49+
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
4950
void DelayUs(uint32_t micros, uint32_t offset_micros) {
5051
const auto kTicks = micros * kTicksPerUs;
5152

@@ -58,7 +59,7 @@ void DelayUs(uint32_t micros, uint32_t offset_micros) {
5859
ticks_previous = offset_micros;
5960
}
6061

61-
while (1) {
62+
while (true) {
6263
const auto kTicksNow = DWT->CYCCNT;
6364

6465
if (kTicksNow != ticks_previous) {

lib-gd32/src/gd32_trng.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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

Comments
 (0)