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 <angus@redyak.com.au>
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy