lpc176x: read chip id and use as usb serial. (#2184)

Signed-off-by: Matt Baker <baker.matt.j@gmail.com>
This commit is contained in:
Matt Baker 2019-11-21 08:54:20 -08:00 committed by KevinOConnor
parent b0a158c271
commit bab27651a1
5 changed files with 82 additions and 10 deletions

View File

@ -50,6 +50,10 @@ config SERIAL_BAUD
Specify the baud rate of the serial port. This should be set Specify the baud rate of the serial port. This should be set
to 250000. Read the FAQ before changing this value. to 250000. Read the FAQ before changing this value.
config HAVE_CHIPID
bool
default n
# Generic configuration options for USB # Generic configuration options for USB
menu "USB ids" menu "USB ids"
depends on USBSERIAL depends on USBSERIAL
@ -61,8 +65,12 @@ config USB_DEVICE_ID
hex "USB device ID" hex "USB device ID"
default 0xabcd default 0xabcd
config USB_SERIAL_NUMBER config USB_SERIAL_NUMBER
string "USB serial number" string "USB serial number" if !USB_SERIAL_NUMBER_CHIPID
default "12345" default "12345"
config USB_SERIAL_NUMBER_CHIPID
depends on HAVE_CHIPID
bool "USB serial number from CHIPID"
default y
endmenu endmenu

View File

@ -358,21 +358,34 @@ usb_req_get_descriptor(struct usb_ctrlrequest *req)
{ {
if (req->bRequestType != USB_DIR_IN) if (req->bRequestType != USB_DIR_IN)
goto fail; goto fail;
uint_fast8_t i; void *desc = NULL;
uint_fast8_t flags, size, i;
for (i=0; i<ARRAY_SIZE(cdc_descriptors); i++) { for (i=0; i<ARRAY_SIZE(cdc_descriptors); i++) {
const struct descriptor_s *d = &cdc_descriptors[i]; const struct descriptor_s *d = &cdc_descriptors[i];
if (READP(d->wValue) == req->wValue if (READP(d->wValue) == req->wValue
&& READP(d->wIndex) == req->wIndex) { && READP(d->wIndex) == req->wIndex) {
uint_fast8_t size = READP(d->size); flags = NEED_PROGMEM ? UX_SEND_PROGMEM : UX_SEND;
uint_fast8_t flags = NEED_PROGMEM ? UX_SEND_PROGMEM : UX_SEND; size = READP(d->size);
if (size > req->wLength) desc = (void*)READP(d->desc);
size = req->wLength;
else if (size < req->wLength)
flags |= UX_SEND_ZLP;
usb_do_xfer((void*)READP(d->desc), size, flags);
return;
} }
} }
if (CONFIG_USB_SERIAL_NUMBER_CHIPID
&& req->wValue == ((USB_DT_STRING<<8) | USB_STR_ID_SERIAL)
&& req->wIndex == USB_LANGID_ENGLISH_US) {
struct usb_string_descriptor *usbserial_serialid;
usbserial_serialid = usbserial_get_serialid();
flags = UX_SEND;
size = usbserial_serialid->bLength;
desc = (void*)usbserial_serialid;
}
if (desc) {
if (size > req->wLength)
size = req->wLength;
else if (size < req->wLength)
flags |= UX_SEND_ZLP;
usb_do_xfer(desc, size, flags);
return;
}
fail: fail:
usb_do_stall(); usb_do_stall();
} }

View File

@ -22,6 +22,7 @@ void usb_stall_ep0(void);
void usb_set_address(uint_fast8_t addr); void usb_set_address(uint_fast8_t addr);
void usb_set_configure(void); void usb_set_configure(void);
void usb_request_bootloader(void); void usb_request_bootloader(void);
struct usb_string_descriptor *usbserial_get_serialid(void);
// usb_cdc.c // usb_cdc.c
void usb_notify_bulk_in(void); void usb_notify_bulk_in(void);

View File

@ -66,4 +66,8 @@ config SERIAL
bool bool
default y default y
config HAVE_CHIPID
bool
default y
endif endif

View File

@ -13,6 +13,7 @@
#include "byteorder.h" // cpu_to_le32 #include "byteorder.h" // cpu_to_le32
#include "command.h" // DECL_CONSTANT_STR #include "command.h" // DECL_CONSTANT_STR
#include "generic/usb_cdc.h" // usb_notify_ep0 #include "generic/usb_cdc.h" // usb_notify_ep0
#include "generic/usbstd.h" // usb_string_descriptor
#include "internal.h" // gpio_peripheral #include "internal.h" // gpio_peripheral
#include "sched.h" // DECL_INIT #include "sched.h" // DECL_INIT
#include "usb_cdc_ep.h" // USB_CDC_EP_BULK_IN #include "usb_cdc_ep.h" // USB_CDC_EP_BULK_IN
@ -34,6 +35,12 @@
#define RD_EN (1<<0) #define RD_EN (1<<0)
#define WR_EN (1<<1) #define WR_EN (1<<1)
// IAP interface
#define IAP_LOCATION 0x1fff1ff1
#define IAP_CMD_READ_UID 58
#define IAP_UID_LEN 16
typedef void (*IAP)(uint32_t *, uint32_t *);
static void static void
usb_irq_disable(void) usb_irq_disable(void)
{ {
@ -104,6 +111,16 @@ sie_select_and_clear(uint32_t idx)
/**************************************************************** /****************************************************************
* Interface * Interface
****************************************************************/ ****************************************************************/
#define USB_STR_SERIAL_CHIPID u"0123456789ABCDEF0123456789ABCDEF"
#define SIZE_cdc_string_serial_chipid \
(sizeof(cdc_string_serial_chipid) + sizeof(USB_STR_SERIAL_CHIPID) - 2)
static struct usb_string_descriptor cdc_string_serial_chipid = {
.bLength = SIZE_cdc_string_serial_chipid,
.bDescriptorType = USB_DT_STRING,
.data = USB_STR_SERIAL_CHIPID,
};
static int_fast8_t static int_fast8_t
usb_write_packet(uint32_t ep, const void *data, uint_fast8_t len) usb_write_packet(uint32_t ep, const void *data, uint_fast8_t len)
@ -260,10 +277,36 @@ usb_request_bootloader(void)
NVIC_SystemReset(); NVIC_SystemReset();
} }
struct usb_string_descriptor *
usbserial_get_serialid(void)
{
return &cdc_string_serial_chipid;
}
/**************************************************************** /****************************************************************
* Setup and interrupts * Setup and interrupts
****************************************************************/ ****************************************************************/
static void
usb_set_serial(void)
{
uint32_t iap_cmd_uid[5] = {IAP_CMD_READ_UID, 0, 0, 0, 0};
uint32_t iap_resp[5];
IAP iap_entry = (IAP)IAP_LOCATION;
__disable_irq();
iap_entry(iap_cmd_uid, iap_resp);
__enable_irq();
uint8_t *chipid = (uint8_t *)&iap_resp[1];
uint8_t i, j, c;
for (i = 0; i < IAP_UID_LEN; i++) {
for (j = 0; j < 2; j++) {
c = (chipid[i] >> 4*j) & 0xF;
c = (c < 10) ? '0'+c : 'A'-10+c;
cdc_string_serial_chipid.data[2*i+((j)?0:1)] = c;
}
}
}
void void
USB_IRQHandler(void) USB_IRQHandler(void)
@ -300,6 +343,9 @@ DECL_CONSTANT_STR("RESERVE_PINS_USB", "P0.30,P0.29,P2.9");
void void
usbserial_init(void) usbserial_init(void)
{ {
if (CONFIG_USB_SERIAL_NUMBER_CHIPID)
usb_set_serial();
usb_irq_disable(); usb_irq_disable();
// enable power // enable power
enable_pclock(PCLK_USB); enable_pclock(PCLK_USB);