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>
This commit is contained in:
parent
f567a9255a
commit
8b1980ad45
|
@ -92,45 +92,9 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
|
|||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq);
|
||||
|
||||
STATIC mp_obj_t machine_unique_id(void) {
|
||||
// Each device has a unique 128-bit serial number which is a concatenation of four 32-bit
|
||||
// words contained at the following addresses. The uniqueness of the serial number is
|
||||
// guaranteed only when using all 128 bits.
|
||||
// Atmel SAM D21E / SAM D21G / SAM D21J
|
||||
// SMART ARM-Based Microcontroller
|
||||
// DATASHEET
|
||||
// 9.6 (SAMD51) or 9.3.3 (or 10.3.3 depending on which manual)(SAMD21) Serial Number
|
||||
//
|
||||
// EXAMPLE (SAMD21)
|
||||
// ----------------
|
||||
// OpenOCD:
|
||||
// Word0:
|
||||
// > at91samd21g18.cpu mdw 0x0080A00C 1
|
||||
// 0x0080a00c: 6e27f15f
|
||||
// Words 1-3:
|
||||
// > at91samd21g18.cpu mdw 0x0080A040 3
|
||||
// 0x0080a040: 50534b54 332e3120 ff091645
|
||||
//
|
||||
// MicroPython (this code and same order as shown in Arduino IDE)
|
||||
// >>> binascii.hexlify(machine.unique_id())
|
||||
// b'6e27f15f50534b54332e3120ff091645'
|
||||
|
||||
#if defined(MCU_SAMD21)
|
||||
uint32_t *id_addresses[4] = {(uint32_t *)0x0080A00C, (uint32_t *)0x0080A040,
|
||||
(uint32_t *)0x0080A044, (uint32_t *)0x0080A048};
|
||||
#elif defined(MCU_SAMD51)
|
||||
uint32_t *id_addresses[4] = {(uint32_t *)0x008061FC, (uint32_t *)0x00806010,
|
||||
(uint32_t *)0x00806014, (uint32_t *)0x00806018};
|
||||
#endif
|
||||
uint8_t raw_id[16];
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int k = 0; k < 4; k++) {
|
||||
// 'Reverse' the read bytes into a 32 bit word (Consistent with Arduino)
|
||||
raw_id[4 * i + k] = (*(id_addresses[i]) >> (24 - k * 8)) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
return mp_obj_new_bytes((byte *)&raw_id, sizeof(raw_id));
|
||||
samd_unique_id_t id;
|
||||
samd_get_unique_id(&id);
|
||||
return mp_obj_new_bytes((byte *)&id.bytes, sizeof(id.bytes));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
|
||||
|
||||
|
|
|
@ -67,6 +67,11 @@
|
|||
#ifndef MICROPY_HW_USB_CDC
|
||||
#define MICROPY_HW_USB_CDC (1)
|
||||
#endif
|
||||
// SAMD unique ID is 16 bytes (hex string == 32)
|
||||
#ifndef MICROPY_HW_USB_DESC_STR_MAX
|
||||
#define MICROPY_HW_USB_DESC_STR_MAX (32)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Control over Python builtins
|
||||
|
|
|
@ -153,3 +153,39 @@ void sercom_deinit_all(void) {
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
void samd_get_unique_id(samd_unique_id_t *id) {
|
||||
// Atmel SAM D21E / SAM D21G / SAM D21J
|
||||
// SMART ARM-Based Microcontroller
|
||||
// DATASHEET
|
||||
// 9.6 (SAMD51) or 9.3.3 (or 10.3.3 depending on which manual)(SAMD21) Serial Number
|
||||
//
|
||||
// EXAMPLE (SAMD21)
|
||||
// ----------------
|
||||
// OpenOCD:
|
||||
// Word0:
|
||||
// > at91samd21g18.cpu mdw 0x0080A00C 1
|
||||
// 0x0080a00c: 6e27f15f
|
||||
// Words 1-3:
|
||||
// > at91samd21g18.cpu mdw 0x0080A040 3
|
||||
// 0x0080a040: 50534b54 332e3120 ff091645
|
||||
//
|
||||
// MicroPython (this code and same order as shown in Arduino IDE)
|
||||
// >>> binascii.hexlify(machine.unique_id())
|
||||
// b'6e27f15f50534b54332e3120ff091645'
|
||||
|
||||
#if defined(MCU_SAMD21)
|
||||
uint32_t *id_addresses[4] = {(uint32_t *)0x0080A00C, (uint32_t *)0x0080A040,
|
||||
(uint32_t *)0x0080A044, (uint32_t *)0x0080A048};
|
||||
#elif defined(MCU_SAMD51)
|
||||
uint32_t *id_addresses[4] = {(uint32_t *)0x008061FC, (uint32_t *)0x00806010,
|
||||
(uint32_t *)0x00806014, (uint32_t *)0x00806018};
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int k = 0; k < 4; k++) {
|
||||
// 'Reverse' the read bytes into a 32 bit word (Consistent with Arduino)
|
||||
id->bytes[4 * i + k] = (*(id_addresses[i]) >> (24 - k * 8)) & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
#include "sam.h"
|
||||
#include "clock_config.h"
|
||||
|
||||
typedef struct _samd_unique_id_t {
|
||||
uint8_t bytes[16];
|
||||
} samd_unique_id_t;
|
||||
|
||||
extern Sercom *sercom_instance[];
|
||||
|
||||
void samd_init(void);
|
||||
|
@ -40,6 +44,10 @@ void USB_Handler_wrapper(void);
|
|||
void sercom_enable(Sercom *spi, int state);
|
||||
void sercom_register_irq(int sercom_id, void (*sercom_irq_handler));
|
||||
|
||||
// Each device has a unique 128-bit serial number. The uniqueness of the serial number is
|
||||
// guaranteed only when using all 128 bits.
|
||||
void samd_get_unique_id(samd_unique_id_t *id);
|
||||
|
||||
#define SERCOM_IRQ_TYPE_UART (0)
|
||||
#define SERCOM_IRQ_TYPE_SPI (1)
|
||||
#define SERCOM_IRQ_TYPE_I2C (2)
|
||||
|
|
|
@ -31,12 +31,13 @@
|
|||
#include "mp_usbd.h"
|
||||
#include "string.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#define SERIAL_TODO "000000000000" // TODO
|
||||
#include "samd_soc.h"
|
||||
|
||||
void mp_usbd_port_get_serial_number(char *serial_buf) {
|
||||
MP_STATIC_ASSERT(sizeof(SERIAL_TODO) <= MICROPY_HW_USB_DESC_STR_MAX);
|
||||
strcpy(serial_buf, SERIAL_TODO);
|
||||
samd_unique_id_t id;
|
||||
samd_get_unique_id(&id);
|
||||
MP_STATIC_ASSERT(sizeof(id.bytes) * 2 <= MICROPY_HW_USB_DESC_STR_MAX);
|
||||
mp_usbd_hex_str(serial_buf, id.bytes, sizeof(id.bytes));
|
||||
}
|
||||
|
||||
void USB_Handler_wrapper(void) {
|
||||
|
|
Loading…
Reference in New Issue