summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2023-08-03 20:42:34 +0700
committerhathach <[email protected]>2023-08-03 20:42:34 +0700
commit041f510f909f0ce8923389c847a8d55e0b7eeee2 (patch)
treecb669dc6e1f4945898f2f0822a86731c293d3dd0
parent1324c2862df921d9634e90a78048f5d71a77d894 (diff)
add board_get_unique_id() for serial number
implemented board_get_unique_id() for rp2040 and L4
-rw-r--r--examples/device/cdc_msc/src/usb_descriptors.c54
-rw-r--r--hw/bsp/board_api.h40
-rw-r--r--hw/bsp/family_support.cmake3
-rw-r--r--hw/bsp/rp2040/family.c36
-rw-r--r--hw/bsp/rp2040/family.cmake1
-rw-r--r--hw/bsp/stm32l4/family.c52
6 files changed, 124 insertions, 62 deletions
diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c
index 44c849277..baf919f84 100644
--- a/examples/device/cdc_msc/src/usb_descriptors.c
+++ b/examples/device/cdc_msc/src/usb_descriptors.c
@@ -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;
+
+ switch(index) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
+
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str+1, 32);
+ break;
- 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
+ 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
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
+ if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
- const char* str = string_desc_arr[index];
+ const char* str = string_desc_arr[index];
- // Cap at max char
- chr_count = (uint8_t) strlen(str);
- if ( chr_count > 31 ) chr_count = 31;
+ // Cap at max char
+ chr_count = strlen(str);
+ if ( chr_count > 31 ) chr_count = 31;
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i<chr_count; i++)
- {
- _desc_str[1+i] = str[i];
- }
+ // 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
diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h
index 7249f618d..53296cd56 100644
--- a/hw/bsp/board_api.h
+++ b/hw/bsp/board_api.h
@@ -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();
diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake
index b2e61a824..e5571b3b5 100644
--- a/hw/bsp/family_support.cmake
+++ b/hw/bsp/family_support.cmake
@@ -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
diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c
index be5e9f753..aa9d00c23 100644
--- a/hw/bsp/rp2040/family.c
+++ b/hw/bsp/rp2040/family.c
@@ -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);
}
diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake
index 17900dd7a..465041b12 100644
--- a/hw/bsp/rp2040/family.cmake
+++ b/hw/bsp/rp2040/family.cmake
@@ -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)
diff --git a/hw/bsp/stm32l4/family.c b/hw/bsp/stm32l4/family.c
index 0b2c22d19..1c6c595f1 100644
--- a/hw/bsp/stm32l4/family.c
+++ b/hw/bsp/stm32l4/family.c
@@ -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;
+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];
+
+ return len;
+}
+
+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);
+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
+#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) {
}