Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ec9be41

Browse files
committed
samd: Use unique id for USB serial number.
Replaces the previous all-zeroes "TODO" serial number. Requires refactoring the low-level unique_id routine out from modmachine.c This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <[email protected]>
1 parent 04b1234 commit ec9be41

File tree

4 files changed

+54
-4
lines changed

4 files changed

+54
-4
lines changed

ports/samd/mpconfigport.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@
6767
#ifndef MICROPY_HW_USB_CDC
6868
#define MICROPY_HW_USB_CDC (1)
6969
#endif
70+
// SAMD unique ID is 16 bytes (hex string == 32)
71+
#ifndef MICROPY_HW_USB_DESC_STR_MAX
72+
#define MICROPY_HW_USB_DESC_STR_MAX (32)
73+
#endif
74+
7075
#endif
7176

7277
// Control over Python builtins

ports/samd/samd_soc.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,39 @@ void sercom_deinit_all(void) {
153153
}
154154

155155
#endif
156+
157+
void samd_get_unique_id(_samd_unique_id_t *id) {
158+
// Atmel SAM D21E / SAM D21G / SAM D21J
159+
// SMART ARM-Based Microcontroller
160+
// DATASHEET
161+
// 9.6 (SAMD51) or 9.3.3 (or 10.3.3 depending on which manual)(SAMD21) Serial Number
162+
//
163+
// EXAMPLE (SAMD21)
164+
// ----------------
165+
// OpenOCD:
166+
// Word0:
167+
// > at91samd21g18.cpu mdw 0x0080A00C 1
168+
// 0x0080a00c: 6e27f15f
169+
// Words 1-3:
170+
// > at91samd21g18.cpu mdw 0x0080A040 3
171+
// 0x0080a040: 50534b54 332e3120 ff091645
172+
//
173+
// MicroPython (this code and same order as shown in Arduino IDE)
174+
// >>> binascii.hexlify(machine.unique_id())
175+
// b'6e27f15f50534b54332e3120ff091645'
176+
177+
#if defined(MCU_SAMD21)
178+
uint32_t *id_addresses[4] = {(uint32_t *)0x0080A00C, (uint32_t *)0x0080A040,
179+
(uint32_t *)0x0080A044, (uint32_t *)0x0080A048};
180+
#elif defined(MCU_SAMD51)
181+
uint32_t *id_addresses[4] = {(uint32_t *)0x008061FC, (uint32_t *)0x00806010,
182+
(uint32_t *)0x00806014, (uint32_t *)0x00806018};
183+
#endif
184+
185+
for (int i = 0; i < 4; i++) {
186+
for (int k = 0; k < 4; k++) {
187+
// 'Reverse' the read bytes into a 32 bit word (Consistent with Arduino)
188+
id->bytes[4 * i + k] = (*(id_addresses[i]) >> (24 - k * 8)) & 0xff;
189+
}
190+
}
191+
}

ports/samd/samd_soc.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ void USB_Handler_wrapper(void);
4040
void sercom_enable(Sercom *spi, int state);
4141
void sercom_register_irq(int sercom_id, void (*sercom_irq_handler));
4242

43+
typedef struct {
44+
uint8_t bytes[16];
45+
} _samd_unique_id_t;
46+
47+
// Each device has a unique 128-bit serial number. The uniqueness of the serial number is
48+
// guaranteed only when using all 128 bits.
49+
void samd_get_unique_id(_samd_unique_id_t *id);
50+
4351
#define SERCOM_IRQ_TYPE_UART (0)
4452
#define SERCOM_IRQ_TYPE_SPI (1)
4553
#define SERCOM_IRQ_TYPE_I2C (2)

ports/samd/usbd.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@
3131
#include "mp_usbd.h"
3232
#include "string.h"
3333
#include "tusb.h"
34-
35-
#define SERIAL_TODO "000000000000" // TODO
34+
#include "samd_soc.h"
3635

3736
void mp_usbd_port_get_serial_number(char *serial_buf) {
38-
MP_STATIC_ASSERT(sizeof(SERIAL_TODO) <= MICROPY_HW_USB_DESC_STR_MAX);
39-
strcpy(serial_buf, SERIAL_TODO);
37+
_samd_unique_id_t id;
38+
samd_get_unique_id(&id);
39+
MP_STATIC_ASSERT(sizeof(id.bytes) * 2 <= MICROPY_HW_USB_DESC_STR_MAX);
40+
mp_usbd_hex_str(serial_buf, id.bytes, sizeof(id.bytes));
4041
}
4142

4243
void USB_Handler_wrapper(void) {

0 commit comments

Comments
 (0)