Skip to content

Commit 7018d61

Browse files
committed
Centralize unique ID memory access
Extract repeated unique ID base address definitions from macaddress.cpp, serialnumber.cpp, and uuid.cpp into a new gd32_unique_id.h header. This reduces code duplication and centralizes MCU variant-specific memory addresses. Update files to use helper functions (Word0, Word1, Word2) instead of inline memory casting.
1 parent 6ebf59b commit 7018d61

5 files changed

Lines changed: 137 additions & 85 deletions

File tree

lib-gd32/include/gd32_unique_id.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* @file gd32_unique_id.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_UNIQUE_ID_H_
27+
#define GD32_UNIQUE_ID_H_
28+
29+
#include <cstdint>
30+
31+
namespace gd32::uid {
32+
#if defined(GD32H7XX)
33+
static constexpr uintptr_t kBase = 0x1FF0F7E8;
34+
#elif defined(GD32F4XX)
35+
static constexpr uintptr_t kBase = 0x1FFF7A10;
36+
#else
37+
static constexpr uintptr_t kBase = 0x1FFFF7E8;
38+
#endif
39+
40+
static inline uint32_t Word(uint32_t index) {
41+
return *reinterpret_cast<volatile const uint32_t*>(kBase + (index * sizeof(uint32_t)));
42+
}
43+
44+
static inline uint32_t Word0() {
45+
return Word(0);
46+
}
47+
static inline uint32_t Word1() {
48+
return Word(1);
49+
}
50+
static inline uint32_t Word2() {
51+
return Word(2);
52+
}
53+
} // namespace gd32::uid
54+
55+
#endif // GD32_UNIQUE_ID_H_

lib-gd32/src/macaddress.cpp

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,18 @@
3030
#include <cstdint>
3131

3232
#include "firmware/debug/debug_debug.h"
33+
#include "gd32_unique_id.h"
3334

3435
void MacAddress(uint8_t paddr[]) {
35-
#if defined(GD32H7XX)
36-
const auto kMacaddressHigh = *reinterpret_cast<volatile uint32_t*>(0x1FF0F7E8);
37-
const auto kMacAddressLow = *reinterpret_cast<volatile uint32_t*>(0x1FF0F7EC);
38-
#elif defined(GD32F4XX)
39-
const auto kMacaddressHigh = *reinterpret_cast<volatile uint32_t*>(0x1FFF7A10);
40-
const auto kMacAddressLow = *reinterpret_cast<volatile uint32_t*>(0x1FFF7A14);
41-
#else
42-
const auto kMacaddressHigh = *reinterpret_cast<volatile uint32_t*>(0x1FFFF7E8);
43-
const auto kMacAddressLow = *reinterpret_cast<volatile uint32_t*>(0x1FFFF7EC);
44-
#endif
36+
const auto kId0 = gd32::uid::Word0();
37+
const auto kId1 = gd32::uid::Word1();
4538

4639
paddr[0] = 2;
47-
paddr[1] = static_cast<uint8_t>((kMacAddressLow >> 0) & 0xFF);
48-
paddr[2] = static_cast<uint8_t>((kMacaddressHigh >> 24) & 0xFF);
49-
paddr[3] = static_cast<uint8_t>((kMacaddressHigh >> 16) & 0xFF);
50-
paddr[4] = static_cast<uint8_t>((kMacaddressHigh >> 8) & 0xFF);
51-
paddr[5] = static_cast<uint8_t>((kMacaddressHigh >> 0) & 0xFF);
40+
paddr[1] = static_cast<uint8_t>((kId1 >> 0) & 0xFF);
41+
paddr[2] = static_cast<uint8_t>((kId0 >> 24) & 0xFF);
42+
paddr[3] = static_cast<uint8_t>((kId0 >> 16) & 0xFF);
43+
paddr[4] = static_cast<uint8_t>((kId0 >> 8) & 0xFF);
44+
paddr[5] = static_cast<uint8_t>((kId0 >> 0) & 0xFF);
5245

5346
DEBUG_PRINTF("%02x:%02x:%02x:%02x:%02x:%02x", paddr[0], paddr[1], paddr[2], paddr[3], paddr[4], paddr[5]);
5447
}

lib-gd32/src/serialnumber.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,13 @@
2626
#include <cstdint>
2727

2828
#include "serialnumber.h"
29+
#include "gd32_unique_id.h"
2930

3031
void SerialNumber(uint8_t sn[kSnSize]) {
31-
#if defined(GD32H7XX)
32-
const auto kMacaddressHigh = *reinterpret_cast<volatile uint32_t*>(0x1FF0F7E8);
33-
#elif defined(GD32F4XX)
34-
const auto kMacaddressHigh = *reinterpret_cast<volatile uint32_t*>(0x1FFF7A10);
35-
#else
36-
const auto kMacaddressHigh = *reinterpret_cast<volatile uint32_t*>(0x1FFFF7E8);
37-
#endif
32+
const auto kId0 = gd32::uid::Word0();
3833

39-
sn[0] = static_cast<uint8_t>((kMacaddressHigh >> 0) & 0xFF);
40-
sn[1] = static_cast<uint8_t>((kMacaddressHigh >> 8) & 0xFF);
41-
sn[2] = static_cast<uint8_t>((kMacaddressHigh >> 16) & 0xFF);
42-
sn[3] = static_cast<uint8_t>((kMacaddressHigh >> 24) & 0xFF);
34+
sn[0] = static_cast<uint8_t>((kId0 >> 0) & 0xFF);
35+
sn[1] = static_cast<uint8_t>((kId0 >> 8) & 0xFF);
36+
sn[2] = static_cast<uint8_t>((kId0 >> 16) & 0xFF);
37+
sn[3] = static_cast<uint8_t>((kId0 >> 24) & 0xFF);
4338
}

lib-gd32/src/softuart0/uart0.cpp

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,61 +22,61 @@
2222
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2323
* THE SOFTWARE.
2424
*/
25-
25+
2626
#include <cstdint>
2727

2828
#include "gd32.h"
2929

30-
#if defined(GD32H7XX)
31-
#define TIMERx TIMER15
32-
#define RCU_TIMERx RCU_TIMER15
30+
#if defined(GD32H7XX) // GD32H7XX
31+
#define TIMERx TIMER15
32+
#define RCU_TIMERx RCU_TIMER15
3333
#define TIMERx_IRQHandler TIMER15_IRQHandler
34-
#define TIMERx_IRQn TIMER15_IRQn
35-
#elif defined(GD32F30X)
36-
#define TIMERx TIMER7
37-
#define RCU_TIMERx RCU_TIMER7
38-
#if defined (GD32F30X_XD)
34+
#define TIMERx_IRQn TIMER15_IRQn
35+
#elif defined(GD32F30X) // GD32F30X
36+
#define TIMERx TIMER7
37+
#define RCU_TIMERx RCU_TIMER7
38+
#if defined(GD32F30X_XD) // GD32F30X_XD
3939
#define TIMERx_IRQHandler TIMER7_UP_TIMER12_IRQHandler
40-
#define TIMERx_IRQn TIMER7_UP_TIMER12_IRQn
40+
#define TIMERx_IRQn TIMER7_UP_TIMER12_IRQn
4141
#else
4242
#define TIMERx_IRQHandler TIMER7_UP_IRQHandler
43-
#define TIMERx_IRQn TIMER7_UP_IRQn
43+
#define TIMERx_IRQn TIMER7_UP_IRQn
4444
#endif
4545
#else
46-
#define TIMERx TIMER9
47-
#define RCU_TIMERx RCU_TIMER9
46+
#define TIMERx TIMER9
47+
#define RCU_TIMERx RCU_TIMER9
4848
#define TIMERx_IRQHandler TIMER0_UP_TIMER9_IRQHandler
49-
#define TIMERx_IRQn TIMER0_UP_TIMER9_IRQn
49+
#define TIMERx_IRQn TIMER0_UP_TIMER9_IRQn
5050
#endif
5151

5252
#if defined(GD32H7XX)
53-
#define TIMER_CLOCK_FREQ (AHB_CLOCK_FREQ)
53+
#define TIMER_CLOCK_FREQ (AHB_CLOCK_FREQ)
5454
#elif defined(GD32F4XX)
55-
#define TIMER_CLOCK_FREQ (APB2_CLOCK_FREQ * 2)
55+
#define TIMER_CLOCK_FREQ (APB2_CLOCK_FREQ * 2)
5656
#else
57-
#define TIMER_CLOCK_FREQ (APB2_CLOCK_FREQ)
57+
#define TIMER_CLOCK_FREQ (APB2_CLOCK_FREQ)
5858
#endif
5959

6060
#if !defined(SOFTUART_TX_PINx)
61-
#define SOFTUART_TX_PINx GPIO_PIN_9
62-
#define SOFTUART_TX_GPIOx GPIOA
63-
#define SOFTUART_TX_RCU_GPIOx RCU_GPIOA
61+
#define SOFTUART_TX_PINx GPIO_PIN_9
62+
#define SOFTUART_TX_GPIOx GPIOA
63+
#define SOFTUART_TX_RCU_GPIOx RCU_GPIOA
6464
#endif
6565

6666
#if defined(SOFTUART0_ENABLE_RX)
6767
#if !defined(SOFTUART_RX_PINx)
68-
#define SOFTUART_RX_PINx GPIO_PIN_10
69-
#define SOFTUART_RX_GPIOx GPIOA
70-
#define SOFTUART_RX_RCU_GPIOx RCU_GPIOA
68+
#define SOFTUART_RX_PINx GPIO_PIN_10
69+
#define SOFTUART_RX_GPIOx GPIOA
70+
#define SOFTUART_RX_RCU_GPIOx RCU_GPIOA
7171
#if defined(GD32H7XX)
7272
#error
7373
#else
74-
#define SOFTUART_RX_TIMERx TIMER0
75-
#define SOFTUART_RX_RCU_TIMERx RCU_TIMER0
76-
#define SOFTUART_RX_EXTIx_IRQHandler EXTI10_15_IRQHandler
77-
#define SOFTUART_RX_EXTIx_IRQn EXTI10_15_IRQn
78-
#define SOFTUART_RX_GPIO_PORT_SOURCE_GPIOx GPIO_PORT_SOURCE_GPIOB
79-
#define SOFTUART_RX_GPIO_PIN_SOURCE_x GPIO_PIN_SOURCE_14
74+
#define SOFTUART_RX_TIMERx TIMER11
75+
#define SOFTUART_RX_RCU_TIMERx RCU_TIMER11
76+
#define SOFTUART_RX_EXTIx_IRQHandler EXTI10_15_IRQHandler
77+
#define SOFTUART_RX_EXTIx_IRQn EXTI10_15_IRQn
78+
#define SOFTUART_RX_GPIO_PORT_SOURCE_GPIOx GPIO_PORT_SOURCE_GPIOB
79+
#define SOFTUART_RX_GPIO_PIN_SOURCE_x GPIO_PIN_SOURCE_14
8080
#endif
8181
#endif // !defined(SOFTUART_RX_PINx)
8282
static_assert(TIMERx != SOFTUART_RX_TIMERx);
@@ -92,7 +92,7 @@ static constexpr uint32_t kTimerPeriod = ((TIMER_CLOCK_FREQ / kBaudRate) - 1U);
9292
static constexpr uint32_t kBufferSize = 128U;
9393

9494
enum class TxState { kIdle, kStartBit, kData, kStopBit };
95-
enum class RxState { kIdle, kVerifyStart, kData, kStopBit };
95+
enum class RxState { kIdle, kStart, kData, kStop };
9696

9797
struct CircularBuffer {
9898
uint8_t buffer[kBufferSize];
@@ -108,6 +108,8 @@ static volatile uint8_t s_tx_shift;
108108
#if defined(SOFTUART0_ENABLE_RX)
109109
static volatile CircularBuffer s_rx_buffer __attribute__((aligned(4)));
110110
static volatile RxState s_rx_state;
111+
static volatile uint8_t s_rx_data;
112+
static volatile uint8_t s_rx_shift;
111113
#endif // defined(SOFTUART0_ENABLE_RX)
112114

113115
extern "C" {
@@ -156,6 +158,35 @@ void TIMERx_IRQHandler() {
156158
}
157159
#if defined(SOFTUART0_ENABLE_RX)
158160
void SOFTUART_RX_EXTIx_IRQHandler() {
161+
if (RESET == exti_interrupt_flag_get(EXTI_14)) {
162+
return;
163+
}
164+
165+
exti_interrupt_flag_clear(EXTI_14);
166+
167+
if (s_rx_state != RxState::kIdle) {
168+
return;
169+
}
170+
171+
if ((GPIO_ISTAT(SOFTUART_RX_GPIOx) & SOFTUART_RX_PINx) != 0U) {
172+
return;
173+
}
174+
175+
s_rx_state = RxState::kStart;
176+
s_rx_data = 0;
177+
s_rx_shift = 0;
178+
179+
exti_interrupt_disable(EXTI_14);
180+
181+
timer_disable(SOFTUART_RX_TIMERx);
182+
timer_counter_value_config(SOFTUART_RX_TIMERx, 0);
183+
184+
// First sample = middle of first data bit
185+
// = 1.5 bit times after falling edge.
186+
timer_channel_output_pulse_value_config(SOFTUART_RX_TIMERx, TIMER_CH_0, (kTimerPeriod * 3U) / 2U);
187+
188+
timer_interrupt_flag_clear(SOFTUART_RX_TIMERx, TIMER_INT_FLAG_CH0);
189+
timer_enable(SOFTUART_RX_TIMERx);
159190
}
160191
#endif
161192
}

lib-gd32/src/uuid.cpp

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,41 +23,19 @@
2323
* THE SOFTWARE.
2424
*/
2525

26-
#if !defined(__clang__)
27-
#pragma GCC push_options
28-
#pragma GCC optimize("O2")
29-
#pragma GCC optimize("no-tree-loop-distribute-patterns")
30-
#pragma GCC optimize("-funroll-loops")
31-
#endif
32-
3326
#include <cstdint>
3427
#include <cstring>
3528
#include <uuid/uuid.h>
3629

37-
#include "gd32.h" // IWYU pragma: keep
38-
39-
typedef union pcast32 {
40-
uuid_t uuid;
41-
uint32_t u32[4];
42-
} _pcast32;
30+
#include "gd32_unique_id.h"
4331

4432
void UuidCopy(uuid_t out) {
45-
_pcast32 cast;
33+
uint32_t words[4];
4634

47-
#if defined(GD32H7XX)
48-
cast.u32[0] = REG32(0x1FF0F7E8);
49-
cast.u32[1] = REG32(0x1FF0F7EC);
50-
cast.u32[2] = REG32(0x1FF0F7F0);
51-
#elif defined(GD32F4XX)
52-
cast.u32[0] = REG32(0x1FFF7A10);
53-
cast.u32[1] = REG32(0x1FFF7A14);
54-
cast.u32[2] = REG32(0x1FFF7A18);
55-
#else
56-
cast.u32[0] = REG32(0x1FFFF7E8);
57-
cast.u32[1] = REG32(0x1FFFF7EC);
58-
cast.u32[2] = REG32(0x1FFFF7F0);
59-
#endif
60-
cast.u32[3] = cast.u32[0] + cast.u32[1] + cast.u32[2];
35+
words[0] = gd32::uid::Word0();
36+
words[1] = gd32::uid::Word1();
37+
words[2] = gd32::uid::Word2();
38+
words[3] = words[0] + words[1] + words[2];
6139

62-
memcpy(out, cast.uuid, sizeof(uuid_t));
40+
memcpy(out, words, sizeof(uuid_t));
6341
}

0 commit comments

Comments
 (0)