add board_get_unique_id() for serial number

implemented board_get_unique_id() for rp2040 and L4
This commit is contained in:
hathach 2023-08-03 20:42:34 +07:00
parent 1324c2862d
commit 041f510f90
No known key found for this signature in database
GPG Key ID: F5D50C6D51D17CBA
6 changed files with 126 additions and 64 deletions

View File

@ -23,6 +23,7 @@
*
*/
#include "bsp/board_api.h"
#include "tusb.h"
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
@ -236,6 +237,14 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// String Descriptors
//--------------------------------------------------------------------+
// String Descriptor Index
enum {
STRID_LANGID = 0,
STRID_MANUFACTURER,
STRID_PRODUCT,
STRID_SERIAL,
};
// array of pointer to string descriptors
char const* string_desc_arr [] =
{
@ -247,7 +256,7 @@ char const* string_desc_arr [] =
"TinyUSB MSC", // 5: MSC Interface
};
static uint16_t _desc_str[32];
static uint16_t _desc_str[32+1];
// Invoked when received GET STRING DESCRIPTOR request
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
@ -255,30 +264,35 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
{
(void) langid;
uint8_t chr_count;
size_t chr_count;
if ( index == 0)
{
memcpy(&_desc_str[1], string_desc_arr[0], 2);
chr_count = 1;
}else
{
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
switch(index) {
case STRID_LANGID:
memcpy(&_desc_str[1], string_desc_arr[0], 2);
chr_count = 1;
break;
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
case STRID_SERIAL:
chr_count = board_usb_get_serial(_desc_str+1, 32);
break;
const char* str = string_desc_arr[index];
default:
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
// Cap at max char
chr_count = (uint8_t) strlen(str);
if ( chr_count > 31 ) chr_count = 31;
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
// Convert ASCII string into UTF-16
for(uint8_t i=0; i<chr_count; i++)
{
_desc_str[1+i] = str[i];
}
const char* str = string_desc_arr[index];
// Cap at max char
chr_count = strlen(str);
if ( chr_count > 31 ) chr_count = 31;
// Convert ASCII string into UTF-16
for(size_t i=0; i<chr_count; i++) {
_desc_str[1+i] = str[i];
}
break;
}
// first byte is length (including header), second byte is string type

View File

@ -60,12 +60,13 @@ void board_led_write(bool state);
// a '1' means active (pressed), a '0' means inactive.
uint32_t board_button_read(void);
// Get characters from UART
// Return number of read bytes
// Get board unique ID for USB serial number. Return number of bytes. Note max_len is typically 16
TU_ATTR_WEAK size_t board_get_unique_id(uint8_t id[], size_t max_len);
// Get characters from UART. Return number of read bytes
int board_uart_read(uint8_t *buf, int len);
// Send characters to UART
// Return number of sent bytes
// Send characters to UART. Return number of sent bytes
int board_uart_write(void const *buf, int len);
#if CFG_TUSB_OS == OPT_OS_NONE
@ -108,6 +109,37 @@ static inline void board_led_off(void) {
board_led_write(false);
}
// Get USB Serial number string from unique ID if available. Return number of character.
// Input is string descriptor from index 1 (index 0 is type + len)
static inline size_t board_usb_get_serial(uint16_t desc_str1[], size_t max_chars) {
uint8_t serial_id[16] TU_ATTR_ALIGNED(4);
size_t serial_len;
if ( board_get_unique_id ) {
serial_len = board_get_unique_id(serial_id, sizeof(serial_id));
}else {
// fixed serial string is 01234567889ABCDEF
*((uint32_t*)(uintptr_t) serial_id) = 0x67452301;
*((uint32_t*)(uintptr_t) (serial_id+4)) = 0xEFCDAB89;
serial_len = 8;
}
if ( serial_len > max_chars / 2 ) serial_len = max_chars / 2;
for ( size_t i = 0; i < serial_len; i++ ) {
for ( size_t j = 0; j < 2; j++ ) {
const char nibble_to_hex[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
uint8_t const nibble = (serial_id[i] >> (j * 4)) & 0xf;
desc_str1[i * 2 + (1 - j)] = nibble_to_hex[nibble]; // UTF-16-LE
}
}
return 2*serial_len;
}
// TODO remove
static inline void board_delay(uint32_t ms) {
uint32_t start_ms = board_millis();

View File

@ -289,7 +289,8 @@ function(family_add_default_example_warnings TARGET)
-Wfatal-errors
-Wdouble-promotion
-Wfloat-equal
-Wshadow
# FIXME commented out because of https://github.com/raspberrypi/pico-sdk/issues/1468
#-Wshadow
-Wwrite-strings
-Wsign-compare
-Wmissing-format-attribute

View File

@ -27,6 +27,7 @@
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "pico/unique_id.h"
#include "hardware/gpio.h"
#include "hardware/sync.h"
#include "hardware/structs/ioqspi.h"
@ -171,17 +172,15 @@ void board_init(void)
// Board porting API
//--------------------------------------------------------------------+
void board_led_write(bool state)
{
void board_led_write(bool state) {
(void) state;
#ifdef LED_PIN
gpio_put(LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
gpio_put(LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON));
#endif
}
uint32_t board_button_read(void)
{
uint32_t board_button_read(void) {
#ifdef BUTTON_BOOTSEL
return BUTTON_STATE_ACTIVE == get_bootsel_button();
#else
@ -189,12 +188,21 @@ uint32_t board_button_read(void)
#endif
}
int board_uart_read(uint8_t* buf, int len)
{
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
pico_unique_board_id_t pico_id;
pico_get_unique_board_id(&pico_id);
size_t len = PICO_UNIQUE_BOARD_ID_SIZE_BYTES;
if (len > max_len) len = max_len;
memcpy(id, pico_id.id, len);
return len;
}
int board_uart_read(uint8_t *buf, int len) {
#ifdef UART_DEV
int count = 0;
while ( (count < len) && uart_is_readable(uart_inst) )
{
while ( (count < len) && uart_is_readable(uart_inst) ) {
buf[count] = uart_getc(uart_inst);
count++;
}
@ -205,11 +213,10 @@ int board_uart_read(uint8_t* buf, int len)
#endif
}
int board_uart_write(void const * buf, int len)
{
int board_uart_write(void const *buf, int len) {
#ifdef UART_DEV
char const* bufch = (char const*) buf;
for(int i=0;i<len;i++) {
char const *bufch = (char const *) buf;
for ( int i = 0; i < len; i++ ) {
uart_putc(uart_inst, bufch[i]);
}
return len;
@ -219,8 +226,7 @@ int board_uart_write(void const * buf, int len)
#endif
}
int board_getchar(void)
{
int board_getchar(void) {
return getchar_timeout_us(0);
}

View File

@ -112,6 +112,7 @@ target_sources(tinyusb_bsp INTERFACE
target_include_directories(tinyusb_bsp INTERFACE
${TOP}/hw
)
target_link_libraries(tinyusb_bsp INTERFACE pico_unique_id)
# tinyusb_additions will hold our extra settings for examples
add_library(tinyusb_additions INTERFACE)

View File

@ -48,8 +48,7 @@ void USB_IRQHandler(void)
UART_HandleTypeDef UartHandle;
void board_init(void)
{
void board_init(void) {
board_clock_init();
// Enable All GPIOs clocks
@ -177,51 +176,60 @@ void board_init(void)
// Board porting API
//--------------------------------------------------------------------+
void board_led_write(bool state)
{
GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1-LED_STATE_ON));
void board_led_write(bool state) {
GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1 - LED_STATE_ON));
HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state);
}
uint32_t board_button_read(void)
{
uint32_t board_button_read(void) {
return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);
}
int board_uart_read(uint8_t* buf, int len)
{
(void) buf; (void) len;
return 0;
}
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
(void) max_len;
volatile uint32_t * stm32_uuid = (volatile uint32_t *) UID_BASE;
uint8_t const len = 12;
uint32_t* id32 = (uint32_t*) (uintptr_t) id;
id32[0] = stm32_uuid[0];
id32[1] = stm32_uuid[1];
id32[2] = stm32_uuid[2];
int board_uart_write(void const * buf, int len)
{
HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff);
return len;
}
#if CFG_TUSB_OS == OPT_OS_NONE
int board_uart_read(uint8_t *buf, int len) {
(void) buf;
(void) len;
return 0;
}
int board_uart_write(void const *buf, int len) {
HAL_UART_Transmit(&UartHandle, (uint8_t *) (uintptr_t) buf, len, 0xffff);
return len;
}
#if CFG_TUSB_OS == OPT_OS_NONE
volatile uint32_t system_ticks = 0;
void SysTick_Handler (void)
{
void SysTick_Handler(void) {
HAL_IncTick();
system_ticks++;
}
uint32_t board_millis(void)
{
uint32_t board_millis(void) {
return system_ticks;
}
#endif
void HardFault_Handler (void)
{
void HardFault_Handler(void) {
__asm("BKPT #0\n");
}
// Required by __libc_init_array in startup code if we are compiling using
// -nostdlib/-nostartfiles.
void _init(void)
{
void _init(void) {
}