From b9c44eea76f92cf3719fd68c9a10b8662faf23b5 Mon Sep 17 00:00:00 2001 From: IngHK Date: Sat, 10 Feb 2024 17:08:29 +0100 Subject: [PATCH 001/382] improved tusb_config.h comment --- examples/host/cdc_msc_hid/src/tusb_config.h | 2 +- examples/host/cdc_msc_hid_freertos/src/tusb_config.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 76d59c316..e4d74077f 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -102,7 +102,7 @@ #define CFG_TUH_ENUMERATION_BUFSIZE 256 #define CFG_TUH_HUB 1 // number of supported hubs -#define CFG_TUH_CDC 1 // CDC ACM +#define CFG_TUH_CDC 1 // number of supported CDC devices. also activates CDC ACM #define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index bb7c3388d..9dc89dc55 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -107,7 +107,7 @@ #define CFG_TUH_ENUMERATION_BUFSIZE 256 #define CFG_TUH_HUB 1 // number of supported hubs -#define CFG_TUH_CDC 1 // CDC ACM +#define CFG_TUH_CDC 1 // number of supported CDC devices. also activates CDC ACM #define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API From 069c68ad04bd6210fc50dbc2aeb2c62448c1731d Mon Sep 17 00:00:00 2001 From: IngHK Date: Fri, 23 Feb 2024 23:27:38 +0100 Subject: [PATCH 002/382] sorted driver functions into Control Request, Driver API, Enumeration and Helper. no functional changes --- src/class/cdc/cdc_host.c | 365 ++++++++++++++++++++------------------- 1 file changed, 192 insertions(+), 173 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 2fb37d835..26eb70c9b 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -782,6 +782,94 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { // ACM //--------------------------------------------------------------------+ +//------------- Driver API -------------// + +static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_VERIFY(p_cdc->acm_capability.support_line_request); + TU_LOG_DRV("CDC ACM Set Control Line State\r\n"); + + tusb_control_request_t const request = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, + .wValue = tu_htole16(line_state), + .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), + .wLength = 0 + }; + + p_cdc->user_control_cb = complete_cb; + + tuh_xfer_t xfer = { + .daddr = p_cdc->daddr, + .ep_addr = 0, + .setup = &request, + .buffer = NULL, + .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call + .user_data = user_data + }; + + TU_ASSERT(tuh_control_xfer(&xfer)); + return true; +} + +static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_LOG_DRV("CDC ACM Set Line Conding\r\n"); + + tusb_control_request_t const request = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_INTERFACE, + .type = TUSB_REQ_TYPE_CLASS, + .direction = TUSB_DIR_OUT + }, + .bRequest = CDC_REQUEST_SET_LINE_CODING, + .wValue = 0, + .wIndex = tu_htole16(p_cdc->bInterfaceNumber), + .wLength = tu_htole16(sizeof(cdc_line_coding_t)) + }; + + // use usbh enum buf to hold line coding since user line_coding variable does not live long enough + uint8_t* enum_buf = usbh_get_enum_buf(); + memcpy(enum_buf, line_coding, sizeof(cdc_line_coding_t)); + + p_cdc->user_control_cb = complete_cb; + tuh_xfer_t xfer = { + .daddr = p_cdc->daddr, + .ep_addr = 0, + .setup = &request, + .buffer = enum_buf, + .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call + .user_data = user_data + }; + + TU_ASSERT(tuh_control_xfer(&xfer)); + return true; +} + +static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_LOG_DRV("CDC ACM Set Data Format\r\n"); + + cdc_line_coding_t line_coding; + line_coding.bit_rate = p_cdc->line_coding.bit_rate; + line_coding.stop_bits = stop_bits; + line_coding.parity = parity; + line_coding.data_bits = data_bits; + + return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data); +} + +static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_VERIFY(p_cdc->acm_capability.support_line_request); + cdc_line_coding_t line_coding = p_cdc->line_coding; + line_coding.bit_rate = baudrate; + return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data); +} + +//------------- Enumeration -------------// + enum { CONFIG_ACM_SET_CONTROL_LINE_STATE = 0, CONFIG_ACM_SET_LINE_CODING, @@ -869,120 +957,14 @@ static void acm_process_config(tuh_xfer_t* xfer) { } } -static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm_capability.support_line_request); - TU_LOG_DRV("CDC ACM Set Control Line State\r\n"); - - tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = tu_htole16(line_state), - .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), - .wLength = 0 - }; - - p_cdc->user_control_cb = complete_cb; - - tuh_xfer_t xfer = { - .daddr = p_cdc->daddr, - .ep_addr = 0, - .setup = &request, - .buffer = NULL, - .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call - .user_data = user_data - }; - - TU_ASSERT(tuh_control_xfer(&xfer)); - return true; -} - -static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_DRV("CDC ACM Set Line Conding\r\n"); - - tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_INTERFACE, - .type = TUSB_REQ_TYPE_CLASS, - .direction = TUSB_DIR_OUT - }, - .bRequest = CDC_REQUEST_SET_LINE_CODING, - .wValue = 0, - .wIndex = tu_htole16(p_cdc->bInterfaceNumber), - .wLength = tu_htole16(sizeof(cdc_line_coding_t)) - }; - - // use usbh enum buf to hold line coding since user line_coding variable does not live long enough - uint8_t* enum_buf = usbh_get_enum_buf(); - memcpy(enum_buf, line_coding, sizeof(cdc_line_coding_t)); - - p_cdc->user_control_cb = complete_cb; - tuh_xfer_t xfer = { - .daddr = p_cdc->daddr, - .ep_addr = 0, - .setup = &request, - .buffer = enum_buf, - .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call - .user_data = user_data - }; - - TU_ASSERT(tuh_control_xfer(&xfer)); - return true; -} - -static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_DRV("CDC ACM Set Data Format\r\n"); - - cdc_line_coding_t line_coding; - line_coding.bit_rate = p_cdc->line_coding.bit_rate; - line_coding.stop_bits = stop_bits; - line_coding.parity = parity; - line_coding.data_bits = data_bits; - - return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data); -} - -static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm_capability.support_line_request); - cdc_line_coding_t line_coding = p_cdc->line_coding; - line_coding.bit_rate = baudrate; - return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data); -} - //--------------------------------------------------------------------+ // FTDI //--------------------------------------------------------------------+ #if CFG_TUH_CDC_FTDI -enum { - CONFIG_FTDI_RESET = 0, - CONFIG_FTDI_MODEM_CTRL, - CONFIG_FTDI_SET_BAUDRATE, - CONFIG_FTDI_SET_DATA, - CONFIG_FTDI_COMPLETE -}; +static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud); -static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { - // FTDI Interface includes 1 vendor interface + 2 bulk endpoints - TU_VERIFY(itf_desc->bInterfaceSubClass == 0xff && itf_desc->bInterfaceProtocol == 0xff && itf_desc->bNumEndpoints == 2); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) <= max_len); - - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); - - TU_LOG_DRV("FTDI opened\r\n"); - p_cdc->serial_drid = SERIAL_DRIVER_FTDI; - - // endpoint pair - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - - // data endpoints expected to be in pairs - return open_ep_stream_pair(p_cdc, desc_ep); -} +//------------- Control Request -------------// // set request without data static bool ftdi_sio_set_request(cdch_interface_t* p_cdc, uint8_t command, uint16_t value, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { @@ -1014,6 +996,20 @@ static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, u return ftdi_sio_set_request(p_cdc, FTDI_SIO_RESET, FTDI_SIO_RESET_SIO, complete_cb, user_data); } +//------------- Driver API -------------// + +static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate); + TU_LOG_DRV("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\r\n", baudrate, divisor); + + p_cdc->user_control_cb = complete_cb; + p_cdc->requested_line_coding.bit_rate = baudrate; + TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, + complete_cb ? cdch_internal_control_complete : NULL, user_data)); + + return true; +} + static bool ftdi_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { (void) p_cdc; @@ -1043,40 +1039,32 @@ static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state return true; } -static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { - const uint8_t divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; - uint32_t divisor; +//------------- Enumeration -------------// - /* divisor shifted 3 bits to the left */ - uint32_t divisor3 = base / (2 * baud); - divisor = (divisor3 >> 3); - divisor |= (uint32_t) divfrac[divisor3 & 0x7] << 14; +enum { + CONFIG_FTDI_RESET = 0, + CONFIG_FTDI_MODEM_CTRL, + CONFIG_FTDI_SET_BAUDRATE, + CONFIG_FTDI_SET_DATA, + CONFIG_FTDI_COMPLETE +}; - /* Deal with special cases for highest baud rates. */ - if (divisor == 1) { /* 1.0 */ - divisor = 0; - } - else if (divisor == 0x4001) { /* 1.5 */ - divisor = 1; - } +static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { + // FTDI Interface includes 1 vendor interface + 2 bulk endpoints + TU_VERIFY(itf_desc->bInterfaceSubClass == 0xff && itf_desc->bInterfaceProtocol == 0xff && itf_desc->bNumEndpoints == 2); + TU_VERIFY(sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) <= max_len); - return divisor; -} + cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); + TU_VERIFY(p_cdc); -static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) { - return ftdi_232bm_baud_base_to_divisor(baud, 48000000u); -} + TU_LOG_DRV("FTDI opened\r\n"); + p_cdc->serial_drid = SERIAL_DRIVER_FTDI; -static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate); - TU_LOG_DRV("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\r\n", baudrate, divisor); + // endpoint pair + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - p_cdc->user_control_cb = complete_cb; - p_cdc->requested_line_coding.bit_rate = baudrate; - TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, - complete_cb ? cdch_internal_control_complete : NULL, user_data)); - - return true; + // data endpoints expected to be in pairs + return open_ep_stream_pair(p_cdc, desc_ep); } static void ftdi_process_config(tuh_xfer_t* xfer) { @@ -1131,39 +1119,40 @@ static void ftdi_process_config(tuh_xfer_t* xfer) { } } +//------------- Helper -------------// + +static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { + const uint8_t divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; + uint32_t divisor; + + /* divisor shifted 3 bits to the left */ + uint32_t divisor3 = base / (2 * baud); + divisor = (divisor3 >> 3); + divisor |= (uint32_t) divfrac[divisor3 & 0x7] << 14; + + /* Deal with special cases for highest baud rates. */ + if (divisor == 1) { /* 1.0 */ + divisor = 0; + } + else if (divisor == 0x4001) { /* 1.5 */ + divisor = 1; + } + + return divisor; +} + +static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) { + return ftdi_232bm_baud_base_to_divisor(baud, 48000000u); +} + #endif //--------------------------------------------------------------------+ // CP210x //--------------------------------------------------------------------+ - #if CFG_TUH_CDC_CP210X -enum { - CONFIG_CP210X_IFC_ENABLE = 0, - CONFIG_CP210X_SET_BAUDRATE, - CONFIG_CP210X_SET_LINE_CTL, - CONFIG_CP210X_SET_DTR_RTS, - CONFIG_CP210X_COMPLETE -}; - -static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - // CP210x Interface includes 1 vendor interface + 2 bulk endpoints - TU_VERIFY(itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0 && itf_desc->bNumEndpoints == 2); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) <= max_len); - - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); - - TU_LOG_DRV("CP210x opened\r\n"); - p_cdc->serial_drid = SERIAL_DRIVER_CP210X; - - // endpoint pair - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - - // data endpoints expected to be in pairs - return open_ep_stream_pair(p_cdc, desc_ep); -} +//------------- Control Request -------------// static bool cp210x_set_request(cdch_interface_t* p_cdc, uint8_t command, uint16_t value, uint8_t* buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request = { @@ -1202,14 +1191,7 @@ static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfe return cp210x_set_request(p_cdc, CP210X_IFC_ENABLE, enabled, NULL, 0, complete_cb, user_data); } -static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - // TODO implement later - (void) p_cdc; - (void) line_coding; - (void) complete_cb; - (void) user_data; - return false; -} +//------------- Driver API -------------// static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG_DRV("CDC CP210x Set BaudRate = %lu\r\n", baudrate); @@ -1231,6 +1213,15 @@ static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, u return false; } +static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // TODO implement later + (void) p_cdc; + (void) line_coding; + (void) complete_cb; + (void) user_data; + return false; +} + static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG_DRV("CDC CP210x Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; @@ -1238,6 +1229,34 @@ static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, complete_cb ? cdch_internal_control_complete : NULL, user_data); } +//------------- Enumeration -------------// + +enum { + CONFIG_CP210X_IFC_ENABLE = 0, + CONFIG_CP210X_SET_BAUDRATE, + CONFIG_CP210X_SET_LINE_CTL, + CONFIG_CP210X_SET_DTR_RTS, + CONFIG_CP210X_COMPLETE +}; + +static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { + // CP210x Interface includes 1 vendor interface + 2 bulk endpoints + TU_VERIFY(itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0 && itf_desc->bNumEndpoints == 2); + TU_VERIFY(sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) <= max_len); + + cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); + TU_VERIFY(p_cdc); + + TU_LOG_DRV("CP210x opened\r\n"); + p_cdc->serial_drid = SERIAL_DRIVER_CP210X; + + // endpoint pair + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + + // data endpoints expected to be in pairs + return open_ep_stream_pair(p_cdc, desc_ep); +} + static void cp210x_process_config(tuh_xfer_t* xfer) { uintptr_t const state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); @@ -1296,7 +1315,7 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bits); static uint16_t ch34x_get_divisor_prescaler(uint32_t baval); -//------------- control request -------------// +//------------- Control Request -------------// static bool ch34x_set_request(cdch_interface_t* p_cdc, uint8_t direction, uint8_t request, uint16_t value, uint16_t index, uint8_t* buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { @@ -1471,6 +1490,7 @@ static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, } //------------- Enumeration -------------// + enum { CONFIG_CH34X_READ_VERSION = 0, CONFIG_CH34X_SERIAL_INIT, @@ -1565,7 +1585,7 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { } } -//------------- CH34x helper -------------// +//------------- Helper -------------// // calculate divisor and prescaler for baudrate, return it as 16-bit combined value static uint16_t ch34x_get_divisor_prescaler(uint32_t baval) { @@ -1654,7 +1674,6 @@ static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bit return lcr; } - #endif // CFG_TUH_CDC_CH34X #endif From 47777a63050f9438d79364436c25d0f6a80dfd55 Mon Sep 17 00:00:00 2001 From: IngHK Date: Tue, 20 Feb 2024 22:08:51 +0100 Subject: [PATCH 003/382] improved TU_LOGs --- src/class/cdc/cdc_host.c | 86 +++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 26eb70c9b..856db32ff 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -41,7 +41,11 @@ #define CFG_TUH_CDC_LOG_LEVEL CFG_TUH_LOG_LEVEL #endif -#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) +#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) +#define TU_LOG_CDC(TXT,DADDR,ITF_NUM,NAME,...) TU_LOG_DRV("[:%u:%u] CDCh %s " TXT "\r\n", \ + DADDR, ITF_NUM, NAME, ##__VA_ARGS__) +#define TU_LOG_P_CDC(TXT,...) TU_LOG_CDC(TXT, p_cdc->daddr, p_cdc->bInterfaceNumber, \ + serial_drivers[p_cdc->serial_drid].name, ##__VA_ARGS__) //--------------------------------------------------------------------+ // Host CDC Interface @@ -169,6 +173,9 @@ typedef struct { bool (*const set_baudrate)(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); bool (*const set_data_format)(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); bool (*const set_line_coding)(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL + uint8_t const * name; + #endif } cdch_serial_driver_t; // Note driver list must be in the same order as SERIAL_DRIVER enum @@ -181,7 +188,10 @@ static const cdch_serial_driver_t serial_drivers[] = { .set_control_line_state = acm_set_control_line_state, .set_baudrate = acm_set_baudrate, .set_data_format = acm_set_data_format, - .set_line_coding = acm_set_line_coding + .set_line_coding = acm_set_line_coding, + #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL + .name = (uint8_t const *) "ACM" + #endif }, #if CFG_TUH_CDC_FTDI @@ -193,7 +203,10 @@ static const cdch_serial_driver_t serial_drivers[] = { .set_control_line_state = ftdi_sio_set_modem_ctrl, .set_baudrate = ftdi_sio_set_baudrate, .set_data_format = ftdi_set_data_format, - .set_line_coding = ftdi_set_line_coding + .set_line_coding = ftdi_set_line_coding, + #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL + .name = (uint8_t const *) "FTDI" + #endif }, #endif @@ -206,7 +219,10 @@ static const cdch_serial_driver_t serial_drivers[] = { .set_control_line_state = cp210x_set_modem_ctrl, .set_baudrate = cp210x_set_baudrate, .set_data_format = cp210x_set_data_format, - .set_line_coding = cp210x_set_line_coding + .set_line_coding = cp210x_set_line_coding, + #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL + .name = (uint8_t const *) "CP210x" + #endif }, #endif @@ -219,7 +235,10 @@ static const cdch_serial_driver_t serial_drivers[] = { .set_control_line_state = ch34x_set_modem_ctrl, .set_baudrate = ch34x_set_baudrate, .set_data_format = ch34x_set_data_format, - .set_line_coding = ch34x_set_line_coding + .set_line_coding = ch34x_set_line_coding, + #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL + .name = (uint8_t const *) "CH34x" + #endif }, #endif }; @@ -408,8 +427,10 @@ static void process_internal_control_complete(tuh_xfer_t* xfer, uint8_t itf_num) cdch_interface_t* p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); uint16_t const value = tu_le16toh(xfer->setup->wValue); + bool const success = (xfer->result == XFER_RESULT_SUCCESS); + TU_LOG_P_CDC("control complete success = %u", success); - if (xfer->result == XFER_RESULT_SUCCESS) { + if (success) { switch (p_cdc->serial_drid) { case SERIAL_DRIVER_ACM: switch (xfer->setup->bRequest) { @@ -525,6 +546,7 @@ static void cdch_internal_control_complete(tuh_xfer_t* xfer) { bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + TU_LOG_P_CDC("set control line state line_state = %u", line_state); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; if (complete_cb) { @@ -548,6 +570,7 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + TU_LOG_P_CDC("set baudrate = %lu", baudrate); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; if (complete_cb) { @@ -572,6 +595,8 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + TU_LOG_P_CDC("set data format data_bits = %u parity = %u stop_bits = %u (indexes!)", + data_bits, parity, stop_bits); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; if (complete_cb) { @@ -597,6 +622,8 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + TU_LOG_P_CDC("set line coding baudrate = %lu data_bits = %u parity = %u stop_bits = %u (indexes!)", + line_coding->bit_rate, line_coding->data_bits, line_coding->parity, line_coding->stop_bits); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; if ( complete_cb ) { @@ -641,7 +668,7 @@ void cdch_close(uint8_t daddr) { for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { cdch_interface_t* p_cdc = &cdch_data[idx]; if (p_cdc->daddr == daddr) { - TU_LOG_DRV(" CDCh close addr = %u index = %u\r\n", daddr, idx); + TU_LOG_P_CDC("close"); // Invoke application callback if (tuh_cdc_umount_cb) tuh_cdc_umount_cb(idx); @@ -722,33 +749,42 @@ static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t co bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; + cdch_serial_driver_t const * driver_detected = NULL; // For CDC: only support ACM subclass // Note: Protocol 0xFF can be RNDIS device if (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass) { - return acm_open(daddr, itf_desc, max_len); - } - else if (SERIAL_DRIVER_COUNT > 1 && - TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { + driver_detected = &serial_drivers[0]; + } else if (SERIAL_DRIVER_COUNT > 1 && TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { uint16_t vid, pid; TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); for (size_t dr = 1; dr < SERIAL_DRIVER_COUNT; dr++) { - cdch_serial_driver_t const* driver = &serial_drivers[dr]; + cdch_serial_driver_t const * driver = &serial_drivers[dr]; for (size_t i = 0; i < driver->vid_pid_count; i++) { if (driver->vid_pid_list[i][0] == vid && driver->vid_pid_list[i][1] == pid) { - return driver->open(daddr, itf_desc, max_len); + driver_detected = driver; + break; } } + if (driver_detected) { + break; + } } } + if (driver_detected) { + TU_LOG_CDC("open", daddr, itf_desc->bInterfaceNumber, driver_detected->name); + bool ret = driver_detected->open(daddr, itf_desc, max_len); + return ret; + } + return false; } static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num) { - TU_LOG_DRV("CDCh Set Configure complete\r\n"); + TU_LOG_P_CDC("set config complete"); p_cdc->mounted = true; if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(idx); @@ -762,6 +798,10 @@ static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t i bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { tusb_control_request_t request; request.wIndex = tu_htole16((uint16_t) itf_num); + uint8_t const idx = tuh_cdc_itf_get_index(daddr, itf_num); + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + TU_LOG_P_CDC("set config"); // fake transfer to kick-off process tuh_xfer_t xfer; @@ -770,10 +810,6 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { xfer.setup = &request; xfer.user_data = 0; // initial state - uint8_t const idx = tuh_cdc_itf_get_index(daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - serial_drivers[p_cdc->serial_drid].process_set_config(&xfer); return true; } @@ -786,7 +822,6 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); - TU_LOG_DRV("CDC ACM Set Control Line State\r\n"); tusb_control_request_t const request = { .bmRequestType_bit = { @@ -816,8 +851,6 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_st } static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_DRV("CDC ACM Set Line Conding\r\n"); - tusb_control_request_t const request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, @@ -850,7 +883,6 @@ static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_DRV("CDC ACM Set Data Format\r\n"); cdc_line_coding_t line_coding; line_coding.bit_rate = p_cdc->line_coding.bit_rate; @@ -1000,7 +1032,6 @@ static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, u static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate); - TU_LOG_DRV("CDC FTDI Set BaudRate = %lu, divisor = 0x%04x\r\n", baudrate, divisor); p_cdc->user_control_cb = complete_cb; p_cdc->requested_line_coding.bit_rate = baudrate; @@ -1032,7 +1063,6 @@ static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t cons } static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_DRV("CDC FTDI Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state, complete_cb ? cdch_internal_control_complete : NULL, user_data)); @@ -1057,7 +1087,6 @@ static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); - TU_LOG_DRV("FTDI opened\r\n"); p_cdc->serial_drid = SERIAL_DRIVER_FTDI; // endpoint pair @@ -1194,7 +1223,6 @@ static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfe //------------- Driver API -------------// static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_DRV("CDC CP210x Set BaudRate = %lu\r\n", baudrate); uint32_t baud_le = tu_htole32(baudrate); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, @@ -1223,7 +1251,6 @@ static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t co } static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_LOG_DRV("CDC CP210x Set Control Line State\r\n"); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, complete_cb ? cdch_internal_control_complete : NULL, user_data); @@ -1247,7 +1274,6 @@ static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); - TU_LOG_DRV("CP210x opened\r\n"); p_cdc->serial_drid = SERIAL_DRIVER_CP210X; // endpoint pair @@ -1508,7 +1534,6 @@ static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uin cdch_interface_t* p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY (p_cdc); - TU_LOG_DRV ("CH34x opened\r\n"); p_cdc->serial_drid = SERIAL_DRIVER_CH34X; tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) tu_desc_next(itf_desc); @@ -1538,14 +1563,13 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { switch (state) { case CONFIG_CH34X_READ_VERSION: - TU_LOG_DRV("[%u] CDCh CH34x attempt to read Chip Version\r\n", p_cdc->daddr); TU_ASSERT (ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, ch34x_process_config, CONFIG_CH34X_SERIAL_INIT),); break; case CONFIG_CH34X_SERIAL_INIT: { // handle version read data, set CH34x line coding (incl. baudrate) uint8_t const version = xfer->buffer[0]; - TU_LOG_DRV("[%u] CDCh CH34x Chip Version = %02x\r\n", p_cdc->daddr, version); + TU_LOG_P_CDC("Chip Version = %02x", version); // only versions >= 0x30 are tested, below 0x30 seems having other programming, see drivers from WCH vendor, Linux kernel and FreeBSD TU_ASSERT (version >= 0x30,); // init CH34x with line coding From 829ea52873387f6fe269c44089c339cfd6d7c64e Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 22 Feb 2024 08:56:15 +0100 Subject: [PATCH 004/382] splitted cdch_internal_control_complete() into driver's _internal_control_complete() and moved them into driver's sections. no functional change --- src/class/cdc/cdc_host.c | 289 +++++++++++++++++++++------------------ 1 file changed, 154 insertions(+), 135 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 856db32ff..e39122e8f 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -286,7 +286,6 @@ static cdch_interface_t* make_new_itf(uint8_t daddr, tusb_desc_interface_t const static bool open_ep_stream_pair(cdch_interface_t* p_cdc , tusb_desc_endpoint_t const *desc_ep); static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num); -static void cdch_internal_control_complete(tuh_xfer_t* xfer); //--------------------------------------------------------------------+ // APPLICATION API @@ -422,127 +421,6 @@ bool tuh_cdc_read_clear (uint8_t idx) { // Control Endpoint API //--------------------------------------------------------------------+ -static void process_internal_control_complete(tuh_xfer_t* xfer, uint8_t itf_num) { - uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t* p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - uint16_t const value = tu_le16toh(xfer->setup->wValue); - bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC("control complete success = %u", success); - - if (success) { - switch (p_cdc->serial_drid) { - case SERIAL_DRIVER_ACM: - switch (xfer->setup->bRequest) { - case CDC_REQUEST_SET_CONTROL_LINE_STATE: - p_cdc->line_state = (uint8_t) value; - break; - - case CDC_REQUEST_SET_LINE_CODING: { - uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength)); - memcpy(&p_cdc->line_coding, xfer->buffer, len); - break; - } - - default: break; - } - break; - - #if CFG_TUH_CDC_FTDI - case SERIAL_DRIVER_FTDI: - switch (xfer->setup->bRequest) { - case FTDI_SIO_MODEM_CTRL: - p_cdc->line_state = (uint8_t) value; - break; - - case FTDI_SIO_SET_BAUD_RATE: - p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; - break; - - default: break; - } - break; - #endif - - #if CFG_TUH_CDC_CP210X - case SERIAL_DRIVER_CP210X: - switch(xfer->setup->bRequest) { - case CP210X_SET_MHS: - p_cdc->line_state = (uint8_t) value; - break; - - case CP210X_SET_BAUDRATE: { - uint32_t baudrate; - memcpy(&baudrate, xfer->buffer, sizeof(uint32_t)); - p_cdc->line_coding.bit_rate = tu_le32toh(baudrate); - break; - } - - default: break; - } - break; - #endif - - #if CFG_TUH_CDC_CH34X - case SERIAL_DRIVER_CH34X: - switch (xfer->setup->bRequest) { - case CH34X_REQ_WRITE_REG: - // register write request - switch (value) { - case CH34X_REG16_DIVISOR_PRESCALER: - // baudrate - p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; - break; - - case CH32X_REG16_LCR2_LCR: - // data format - p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; - p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; - p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; - break; - - default: break; - } - break; - - case CH34X_REQ_MODEM_CTRL: { - // set modem controls RTS/DTR request. Note: signals are inverted - uint16_t const modem_signal = ~value; - if (modem_signal & CH34X_BIT_RTS) { - p_cdc->line_state |= CDC_CONTROL_LINE_STATE_RTS; - } else { - p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_RTS; - } - - if (modem_signal & CH34X_BIT_DTR) { - p_cdc->line_state |= CDC_CONTROL_LINE_STATE_DTR; - } else { - p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_DTR; - } - break; - } - - default: break; - } - break; - #endif - - default: break; - } - } - - xfer->complete_cb = p_cdc->user_control_cb; - if (xfer->complete_cb) { - xfer->complete_cb(xfer); - } -} - -// internal control complete to update state such as line state, encoding -static void cdch_internal_control_complete(tuh_xfer_t* xfer) { - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - process_internal_control_complete(xfer, itf_num); -} - bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t* p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); @@ -820,6 +698,36 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { //------------- Driver API -------------// +// internal control complete to update state such as line state, encoding +static void acm_internal_control_complete(tuh_xfer_t * xfer) { + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); + bool const success = (xfer->result == XFER_RESULT_SUCCESS); + TU_LOG_P_CDC("control complete success = %u", success); + + if (success) { + switch (xfer->setup->bRequest) { + case CDC_REQUEST_SET_CONTROL_LINE_STATE: + p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue); + break; + + case CDC_REQUEST_SET_LINE_CODING: + uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength)); + memcpy(&p_cdc->line_coding, xfer->buffer, len); + break; + + default: break; + } + } + + xfer->complete_cb = p_cdc->user_control_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } +} + static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); @@ -842,7 +750,7 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_st .ep_addr = 0, .setup = &request, .buffer = NULL, - .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call + .complete_cb = complete_cb ? acm_internal_control_complete : NULL, // complete_cb is NULL for sync call .user_data = user_data }; @@ -873,7 +781,7 @@ static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const .ep_addr = 0, .setup = &request, .buffer = enum_buf, - .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, // complete_cb is NULL for sync call + .complete_cb = complete_cb ? acm_internal_control_complete : NULL, // complete_cb is NULL for sync call .user_data = user_data }; @@ -1030,13 +938,42 @@ static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, u //------------- Driver API -------------// +// internal control complete to update state such as line state, line_coding +static void ftdi_internal_control_complete(tuh_xfer_t * xfer) { + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); + bool const success = (xfer->result == XFER_RESULT_SUCCESS); + TU_LOG_P_CDC("control complete success = %u", success); + + if (success) { + switch (xfer->setup->bRequest) { + case FTDI_SIO_MODEM_CTRL: + p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue); + break; + + case FTDI_SIO_SET_BAUD_RATE: + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + break; + + default: break; + } + } + + xfer->complete_cb = p_cdc->user_control_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } +} + static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate); p_cdc->user_control_cb = complete_cb; p_cdc->requested_line_coding.bit_rate = baudrate; TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, - complete_cb ? cdch_internal_control_complete : NULL, user_data)); + complete_cb ? ftdi_internal_control_complete : NULL, user_data)); return true; } @@ -1065,7 +1002,7 @@ static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t cons static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state, - complete_cb ? cdch_internal_control_complete : NULL, user_data)); + complete_cb ? ftdi_internal_control_complete : NULL, user_data)); return true; } @@ -1222,11 +1159,42 @@ static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfe //------------- Driver API -------------// +// internal control complete to update state such as line state, encoding +static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); + bool const success = (xfer->result == XFER_RESULT_SUCCESS); + TU_LOG_P_CDC("control complete success = %u", success); + + if (success) { + switch(xfer->setup->bRequest) { + case CP210X_SET_MHS: + p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue); + break; + + case CP210X_SET_BAUDRATE: + uint32_t baudrate; + memcpy(&baudrate, xfer->buffer, sizeof(uint32_t)); + p_cdc->line_coding.bit_rate = tu_le32toh(baudrate); + break; + + default: break; + } + } + + xfer->complete_cb = p_cdc->user_control_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } +} + static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint32_t baud_le = tu_htole32(baudrate); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, - complete_cb ? cdch_internal_control_complete : NULL, user_data); + complete_cb ? cp210x_internal_control_complete : NULL, user_data); } static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, @@ -1253,7 +1221,7 @@ static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t co static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, - complete_cb ? cdch_internal_control_complete : NULL, user_data); + complete_cb ? cp210x_internal_control_complete : NULL, user_data); } //------------- Enumeration -------------// @@ -1412,9 +1380,60 @@ static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, //------------- Driver API -------------// // internal control complete to update state such as line state, encoding -static void ch34x_control_complete(tuh_xfer_t* xfer) { - // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber - process_internal_control_complete(xfer, 0); +static void ch34x_internal_control_complete(tuh_xfer_t * xfer) { + // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber + uint8_t const itf_num = 0; + uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); + bool const success = (xfer->result == XFER_RESULT_SUCCESS); + TU_LOG_P_CDC("control complete success = %u", success); + + if (success) { + switch (xfer->setup->bRequest) { + case CH34X_REQ_WRITE_REG: + // register write request + switch (tu_le16toh(xfer->setup->wValue)) { + case CH34X_REG16_DIVISOR_PRESCALER: + // baudrate + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + break; + + case CH32X_REG16_LCR2_LCR: + // data format + p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; + p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; + p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; + break; + + default: break; + } + break; + + case CH34X_REQ_MODEM_CTRL: + // set modem controls RTS/DTR request. Note: signals are inverted + uint16_t const modem_signal = ~tu_le16toh(xfer->setup->wValue); + if (modem_signal & CH34X_BIT_RTS) { + p_cdc->line_state |= CDC_CONTROL_LINE_STATE_RTS; + } else { + p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_RTS; + } + + if (modem_signal & CH34X_BIT_DTR) { + p_cdc->line_state |= CDC_CONTROL_LINE_STATE_DTR; + } else { + p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_DTR; + } + break; + + default: break; + } + } + + xfer->complete_cb = p_cdc->user_control_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } } static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, @@ -1426,7 +1445,7 @@ static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, ui uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits); TU_VERIFY(lcr); TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr, - complete_cb ? ch34x_control_complete : NULL, user_data)); + complete_cb ? ch34x_internal_control_complete : NULL, user_data)); return true; } @@ -1435,7 +1454,7 @@ static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, p_cdc->requested_line_coding.bit_rate = baudrate; p_cdc->user_control_cb = complete_cb; TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, baudrate, - complete_cb ? ch34x_control_complete : NULL, user_data)); + complete_cb ? ch34x_internal_control_complete : NULL, user_data)); return true; } @@ -1450,7 +1469,7 @@ static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) { // stage 1 success, continue to stage 2 p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; TU_ASSERT(ch34x_set_data_format(p_cdc, p_cdc->requested_line_coding.stop_bits, p_cdc->requested_line_coding.parity, - p_cdc->requested_line_coding.data_bits, ch34x_control_complete, xfer->user_data), ); + p_cdc->requested_line_coding.data_bits, ch34x_internal_control_complete, xfer->user_data), ); } else { // stage 1 failed, notify user xfer->complete_cb = p_cdc->user_control_cb; @@ -1511,7 +1530,7 @@ static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, p_cdc->user_control_cb = complete_cb; TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, - complete_cb ? ch34x_control_complete : NULL, user_data)); + complete_cb ? ch34x_internal_control_complete : NULL, user_data)); return true; } From 2f50f5a4263dc3d65f3bf96b593edac5ac271a5a Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 22 Feb 2024 14:59:16 +0100 Subject: [PATCH 005/382] changed to use of p_cdc->requested_line_coding --- src/class/cdc/cdc_host.c | 215 +++++++++++++++++---------------------- 1 file changed, 96 insertions(+), 119 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index e39122e8f..b2ba7c9ea 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -63,12 +63,10 @@ typedef struct { cdc_acm_capability_t acm_capability; TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; // Baudrate, stop bits, parity, data width - uint8_t line_state; // DTR (bit0), RTS (bit1) - - #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X - cdc_line_coding_t requested_line_coding; + TU_ATTR_ALIGNED(4) cdc_line_coding_t requested_line_coding; // 1 byte padding - #endif + + uint8_t line_state; // DTR (bit0), RTS (bit1) tuh_xfer_cb_t user_control_cb; @@ -95,9 +93,9 @@ static cdch_interface_t cdch_data[CFG_TUH_CDC]; static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); static void acm_process_config(tuh_xfer_t* xfer); -static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); //------------- FTDI prototypes -------------// @@ -109,9 +107,9 @@ static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST}; static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); static void ftdi_process_config(tuh_xfer_t* xfer); -static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif @@ -124,9 +122,9 @@ static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIS static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); static void cp210x_process_config(tuh_xfer_t* xfer); -static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif @@ -139,9 +137,9 @@ static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST} static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len); static void ch34x_process_config(tuh_xfer_t* xfer); -static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif @@ -170,9 +168,9 @@ typedef struct { bool (*const open)(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); void (*const process_set_config)(tuh_xfer_t* xfer); bool (*const set_control_line_state)(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_baudrate)(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_data_format)(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_line_coding)(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_baudrate)(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_data_format)(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_line_coding)(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL uint8_t const * name; #endif @@ -276,6 +274,7 @@ static cdch_interface_t* make_new_itf(uint8_t daddr, tusb_desc_interface_t const p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber; p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass; p_cdc->bInterfaceProtocol = itf_desc->bInterfaceProtocol; + p_cdc->line_coding = (cdc_line_coding_t) { 0, 0, 0, 0 }; p_cdc->line_state = 0; return p_cdc; } @@ -451,12 +450,14 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete TU_LOG_P_CDC("set baudrate = %lu", baudrate); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; + p_cdc->requested_line_coding.bit_rate = baudrate; + if (complete_cb) { - return driver->set_baudrate(p_cdc, baudrate, complete_cb, user_data); + return driver->set_baudrate(p_cdc, complete_cb, user_data); } else { // blocking xfer_result_t result = XFER_RESULT_INVALID; - bool ret = driver->set_baudrate(p_cdc, baudrate, complete_cb, (uintptr_t) &result); + bool ret = driver->set_baudrate(p_cdc, complete_cb, (uintptr_t) &result); if (user_data) { // user_data is not NULL, return result via user_data @@ -477,12 +478,16 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin data_bits, parity, stop_bits); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; + p_cdc->requested_line_coding.stop_bits = stop_bits; + p_cdc->requested_line_coding.parity = parity; + p_cdc->requested_line_coding.data_bits = data_bits; + if (complete_cb) { - return driver->set_data_format(p_cdc, stop_bits, parity, data_bits, complete_cb, user_data); + return driver->set_data_format(p_cdc, complete_cb, user_data); } else { // blocking xfer_result_t result = XFER_RESULT_INVALID; - bool ret = driver->set_data_format(p_cdc, stop_bits, parity, data_bits, complete_cb, (uintptr_t) &result); + bool ret = driver->set_data_format(p_cdc, complete_cb, (uintptr_t) &result); if (user_data) { // user_data is not NULL, return result via user_data @@ -491,7 +496,7 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); p_cdc->line_coding.stop_bits = stop_bits; - p_cdc->line_coding.parity = parity; + p_cdc->line_coding.parity = parity; p_cdc->line_coding.data_bits = data_bits; return true; } @@ -504,12 +509,14 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, line_coding->bit_rate, line_coding->data_bits, line_coding->parity, line_coding->stop_bits); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; + p_cdc->requested_line_coding = *line_coding; + if ( complete_cb ) { - return driver->set_line_coding(p_cdc, line_coding, complete_cb, user_data); + return driver->set_line_coding(p_cdc, complete_cb, user_data); } else { // blocking xfer_result_t result = XFER_RESULT_INVALID; - bool ret = driver->set_line_coding(p_cdc, line_coding, complete_cb, (uintptr_t) &result); + bool ret = driver->set_line_coding(p_cdc, complete_cb, (uintptr_t) &result); if (user_data) { // user_data is not NULL, return result via user_data @@ -714,8 +721,7 @@ static void acm_internal_control_complete(tuh_xfer_t * xfer) { break; case CDC_REQUEST_SET_LINE_CODING: - uint16_t const len = tu_min16(sizeof(cdc_line_coding_t), tu_le16toh(xfer->setup->wLength)); - memcpy(&p_cdc->line_coding, xfer->buffer, len); + p_cdc->line_coding = p_cdc->requested_line_coding; break; default: break; @@ -758,7 +764,7 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_st return true; } -static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, @@ -773,7 +779,7 @@ static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const // use usbh enum buf to hold line coding since user line_coding variable does not live long enough uint8_t* enum_buf = usbh_get_enum_buf(); - memcpy(enum_buf, line_coding, sizeof(cdc_line_coding_t)); + memcpy(enum_buf, &p_cdc->requested_line_coding, sizeof(cdc_line_coding_t)); p_cdc->user_control_cb = complete_cb; tuh_xfer_t xfer = { @@ -789,23 +795,19 @@ static bool acm_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const return true; } -static bool acm_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->requested_line_coding.bit_rate = p_cdc->line_coding.bit_rate; - cdc_line_coding_t line_coding; - line_coding.bit_rate = p_cdc->line_coding.bit_rate; - line_coding.stop_bits = stop_bits; - line_coding.parity = parity; - line_coding.data_bits = data_bits; - - return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data); + return acm_set_line_coding(p_cdc, complete_cb, user_data); } -static bool acm_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->requested_line_coding.stop_bits = p_cdc->line_coding.stop_bits; + p_cdc->requested_line_coding.parity = p_cdc->line_coding.parity; + p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits; TU_VERIFY(p_cdc->acm_capability.support_line_request); - cdc_line_coding_t line_coding = p_cdc->line_coding; - line_coding.bit_rate = baudrate; - return acm_set_line_coding(p_cdc, &line_coding, complete_cb, user_data); + + return acm_set_line_coding(p_cdc, complete_cb, user_data); } //------------- Enumeration -------------// @@ -879,11 +881,11 @@ static void acm_process_config(tuh_xfer_t* xfer) { case CONFIG_ACM_SET_LINE_CODING: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - if (p_cdc->acm_capability.support_line_request) { - cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(acm_set_line_coding(p_cdc, &line_coding, acm_process_config, CONFIG_ACM_COMPLETE),); - break; - } + if (p_cdc->acm_capability.support_line_request) { + p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + TU_ASSERT(acm_set_line_coding(p_cdc, acm_process_config, CONFIG_ACM_COMPLETE),); + break; + } #endif TU_ATTR_FALLTHROUGH; @@ -902,7 +904,7 @@ static void acm_process_config(tuh_xfer_t* xfer) { //--------------------------------------------------------------------+ #if CFG_TUH_CDC_FTDI -static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud); +static uint32_t ftdi_232bm_baud_to_divisor(cdch_interface_t* p_cdc); //------------- Control Request -------------// @@ -967,32 +969,26 @@ static void ftdi_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(baudrate); +static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(p_cdc); p_cdc->user_control_cb = complete_cb; - p_cdc->requested_line_coding.bit_rate = baudrate; TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); return true; } -static bool ftdi_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ftdi_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { (void) p_cdc; - (void) stop_bits; - (void) parity; - (void) data_bits; (void) complete_cb; (void) user_data; // TODO not implemented yet return false; } -static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { (void) p_cdc; - (void) line_coding; (void) complete_cb; (void) user_data; // TODO not implemented yet @@ -1056,11 +1052,11 @@ static void ftdi_process_config(tuh_xfer_t* xfer) { case CONFIG_FTDI_SET_BAUDRATE: { #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(ftdi_sio_set_baudrate(p_cdc, line_coding.bit_rate, ftdi_process_config, CONFIG_FTDI_SET_DATA),); - break; + p_cdc->requested_line_coding.bit_rate = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM).bit_rate; + TU_ASSERT(ftdi_sio_set_baudrate(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_DATA),); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif } @@ -1107,8 +1103,8 @@ static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { return divisor; } -static uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) { - return ftdi_232bm_baud_base_to_divisor(baud, 48000000u); +static uint32_t ftdi_232bm_baud_to_divisor(cdch_interface_t* p_cdc) { + return ftdi_232bm_baud_base_to_divisor(p_cdc->requested_line_coding.bit_rate, 48000000u); } #endif @@ -1175,9 +1171,7 @@ static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { break; case CP210X_SET_BAUDRATE: - uint32_t baudrate; - memcpy(&baudrate, xfer->buffer, sizeof(uint32_t)); - p_cdc->line_coding.bit_rate = tu_le32toh(baudrate); + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; break; default: break; @@ -1190,29 +1184,24 @@ static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint32_t baud_le = tu_htole32(baudrate); +static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint32_t baud_le = tu_htole32(p_cdc->requested_line_coding.bit_rate); p_cdc->user_control_cb = complete_cb; return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, complete_cb ? cp210x_internal_control_complete : NULL, user_data); } -static bool cp210x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool cp210x_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { (void) p_cdc; - (void) stop_bits; - (void) parity; - (void) data_bits; (void) complete_cb; (void) user_data; // TODO not implemented yet return false; } -static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // TODO implement later (void) p_cdc; - (void) line_coding; (void) complete_cb; (void) user_data; return false; @@ -1265,11 +1254,11 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { case CONFIG_CP210X_SET_BAUDRATE: { #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(cp210x_set_baudrate(p_cdc, line_coding.bit_rate, cp210x_process_config, CONFIG_CP210X_SET_LINE_CTL),); - break; + p_cdc->requested_line_coding.bit_rate = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM).bit_rate; + TU_ASSERT(cp210x_set_baudrate(p_cdc, cp210x_process_config, CONFIG_CP210X_SET_LINE_CTL),); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif } @@ -1306,8 +1295,8 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { #if CFG_TUH_CDC_CH34X -static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bits); -static uint16_t ch34x_get_divisor_prescaler(uint32_t baval); +static uint8_t ch34x_get_lcr(cdch_interface_t * p_cdc); +static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t * p_cdc); //------------- Control Request -------------// @@ -1368,9 +1357,8 @@ static inline bool ch34x_write_reg(cdch_interface_t* p_cdc, uint16_t reg, uint16 // return ch34x_control_in ( p_cdc, CH34X_REQ_READ_REG, reg, 0, buffer, buffersize, complete_cb, user_data ); //} -static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint16_t const div_ps = ch34x_get_divisor_prescaler(baudrate); +static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc); TU_VERIFY(div_ps); TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, complete_cb, user_data)); @@ -1436,25 +1424,17 @@ static void ch34x_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool ch34x_set_data_format(cdch_interface_t* p_cdc, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->requested_line_coding.stop_bits = stop_bits; - p_cdc->requested_line_coding.parity = parity; - p_cdc->requested_line_coding.data_bits = data_bits; - - uint8_t const lcr = ch34x_get_lcr(stop_bits, parity, data_bits); +static bool ch34x_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint8_t const lcr = ch34x_get_lcr(p_cdc); TU_VERIFY(lcr); TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); return true; } -static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, uint32_t baudrate, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->requested_line_coding.bit_rate = baudrate; +static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; - TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, baudrate, - complete_cb ? ch34x_internal_control_complete : NULL, user_data)); + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); return true; } @@ -1468,8 +1448,7 @@ static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) { if (xfer->result == XFER_RESULT_SUCCESS) { // stage 1 success, continue to stage 2 p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; - TU_ASSERT(ch34x_set_data_format(p_cdc, p_cdc->requested_line_coding.stop_bits, p_cdc->requested_line_coding.parity, - p_cdc->requested_line_coding.data_bits, ch34x_internal_control_complete, xfer->user_data), ); + TU_ASSERT(ch34x_set_data_format(p_cdc, ch34x_internal_control_complete, xfer->user_data), ); } else { // stage 1 failed, notify user xfer->complete_cb = p_cdc->user_control_cb; @@ -1480,31 +1459,24 @@ static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) { } // 2 stages: set baudrate (stage1) + set data format (stage2) -static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, cdc_line_coding_t const* line_coding, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->requested_line_coding = *line_coding; +static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; if (complete_cb) { // stage 1 set baudrate - TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate, - ch34x_set_line_coding_stage1_complete, user_data)); + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, ch34x_set_line_coding_stage1_complete, user_data)); } else { // sync call xfer_result_t result; // stage 1 set baudrate - TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, line_coding->bit_rate, NULL, (uintptr_t) &result)); + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, NULL, (uintptr_t) &result)); TU_VERIFY(result == XFER_RESULT_SUCCESS); - p_cdc->line_coding.bit_rate = line_coding->bit_rate; + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; // stage 2 set data format - TU_ASSERT(ch34x_set_data_format(p_cdc, line_coding->stop_bits, line_coding->parity, line_coding->data_bits, - NULL, (uintptr_t) &result)); + TU_ASSERT(ch34x_set_data_format(p_cdc, NULL, (uintptr_t) &result)); TU_VERIFY(result == XFER_RESULT_SUCCESS); - p_cdc->line_coding.stop_bits = line_coding->stop_bits; - p_cdc->line_coding.parity = line_coding->parity; - p_cdc->line_coding.data_bits = line_coding->data_bits; // update transfer result, user_data is expected to point to xfer_result_t if (user_data) { @@ -1592,10 +1564,10 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { // only versions >= 0x30 are tested, below 0x30 seems having other programming, see drivers from WCH vendor, Linux kernel and FreeBSD TU_ASSERT (version >= 0x30,); // init CH34x with line coding - cdc_line_coding_t const line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; - uint16_t const div_ps = ch34x_get_divisor_prescaler(line_coding.bit_rate); + p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; + uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc); TU_ASSERT(div_ps, ); - uint8_t const lcr = ch34x_get_lcr(line_coding.stop_bits, line_coding.parity, line_coding.data_bits); + uint8_t const lcr = ch34x_get_lcr(p_cdc); TU_ASSERT(lcr, ); TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, tu_u16(lcr, 0x9c), div_ps, ch34x_process_config, CONFIG_CH34X_SPECIAL_REG_WRITE),); @@ -1604,7 +1576,7 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { case CONFIG_CH34X_SPECIAL_REG_WRITE: // overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver - p_cdc->line_coding = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X); + p_cdc->line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; TU_ASSERT (ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL),); break; @@ -1631,7 +1603,8 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { //------------- Helper -------------// // calculate divisor and prescaler for baudrate, return it as 16-bit combined value -static uint16_t ch34x_get_divisor_prescaler(uint32_t baval) { +static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t * p_cdc) { + uint32_t const baval = p_cdc->requested_line_coding.bit_rate; uint8_t a; uint8_t b; uint32_t c; @@ -1680,7 +1653,11 @@ static uint16_t ch34x_get_divisor_prescaler(uint32_t baval) { } // calculate lcr value from data coding -static uint8_t ch34x_get_lcr(uint8_t stop_bits, uint8_t parity, uint8_t data_bits) { +static uint8_t ch34x_get_lcr(cdch_interface_t * p_cdc) { + uint8_t const stop_bits = p_cdc->requested_line_coding.stop_bits; + uint8_t const parity = p_cdc->requested_line_coding.parity; + uint8_t const data_bits = p_cdc->requested_line_coding.data_bits; + uint8_t lcr = CH34X_LCR_ENABLE_RX | CH34X_LCR_ENABLE_TX; TU_VERIFY(data_bits >= 5 && data_bits <= 8, 0); lcr |= (uint8_t) (data_bits - 5); From 7dd435cb877f5d3e0b9576dfcdb8c40e9a03c399 Mon Sep 17 00:00:00 2001 From: IngHK Date: Tue, 20 Feb 2024 20:45:50 +0100 Subject: [PATCH 006/382] changed to use of p_cdc->requested_line_state --- src/class/cdc/cdc_host.c | 82 +++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 44 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index b2ba7c9ea..0af429e4b 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -67,6 +67,7 @@ typedef struct { // 1 byte padding uint8_t line_state; // DTR (bit0), RTS (bit1) + uint8_t requested_line_state; tuh_xfer_cb_t user_control_cb; @@ -96,7 +97,7 @@ static void acm_process_config(tuh_xfer_t* xfer); static bool acm_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_control_line_state(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); //------------- FTDI prototypes -------------// #if CFG_TUH_CDC_FTDI @@ -110,7 +111,7 @@ static void ftdi_process_config(tuh_xfer_t* xfer); static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ftdi_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif //------------- CP210X prototypes -------------// @@ -125,7 +126,7 @@ static void cp210x_process_config(tuh_xfer_t* xfer); static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool cp210x_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif //------------- CH34x prototypes -------------// @@ -140,7 +141,7 @@ static void ch34x_process_config(tuh_xfer_t* xfer); static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ch34x_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif //------------- Common -------------// @@ -167,7 +168,7 @@ typedef struct { uint16_t const vid_pid_count; bool (*const open)(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); void (*const process_set_config)(tuh_xfer_t* xfer); - bool (*const set_control_line_state)(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_control_line_state)(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); bool (*const set_baudrate)(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); bool (*const set_data_format)(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); bool (*const set_line_coding)(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -426,12 +427,14 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c TU_LOG_P_CDC("set control line state line_state = %u", line_state); cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; + p_cdc->requested_line_state = (uint8_t) line_state; + if (complete_cb) { - return driver->set_control_line_state(p_cdc, line_state, complete_cb, user_data); + return driver->set_control_line_state(p_cdc, complete_cb, user_data); } else { // blocking xfer_result_t result = XFER_RESULT_INVALID; - bool ret = driver->set_control_line_state(p_cdc, line_state, complete_cb, (uintptr_t) &result); + bool ret = driver->set_control_line_state(p_cdc, complete_cb, (uintptr_t) &result); if (user_data) { // user_data is not NULL, return result via user_data @@ -717,7 +720,7 @@ static void acm_internal_control_complete(tuh_xfer_t * xfer) { if (success) { switch (xfer->setup->bRequest) { case CDC_REQUEST_SET_CONTROL_LINE_STATE: - p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue); + p_cdc->line_state = p_cdc->requested_line_state; break; case CDC_REQUEST_SET_LINE_CODING: @@ -734,7 +737,7 @@ static void acm_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_control_line_state(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); tusb_control_request_t const request = { @@ -744,7 +747,7 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, uint16_t line_st .direction = TUSB_DIR_OUT }, .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = tu_htole16(line_state), + .wValue = tu_htole16(p_cdc->requested_line_state), .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), .wLength = 0 }; @@ -872,10 +875,11 @@ static void acm_process_config(tuh_xfer_t* xfer) { switch (state) { case CONFIG_ACM_SET_CONTROL_LINE_STATE: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - if (p_cdc->acm_capability.support_line_request) { - TU_ASSERT(acm_set_control_line_state(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, acm_process_config, CONFIG_ACM_SET_LINE_CODING),); - break; - } + if (p_cdc->acm_capability.support_line_request) { + p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + TU_ASSERT(acm_set_control_line_state(p_cdc, acm_process_config, CONFIG_ACM_SET_LINE_CODING),); + break; + } #endif TU_ATTR_FALLTHROUGH; @@ -952,7 +956,7 @@ static void ftdi_internal_control_complete(tuh_xfer_t * xfer) { if (success) { switch (xfer->setup->bRequest) { case FTDI_SIO_MODEM_CTRL: - p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue); + p_cdc->line_state = p_cdc->requested_line_state; break; case FTDI_SIO_SET_BAUD_RATE: @@ -995,9 +999,9 @@ static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete return false; } -static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; - TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | line_state, + TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | p_cdc->requested_line_state, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); return true; } @@ -1044,10 +1048,11 @@ static void ftdi_process_config(tuh_xfer_t* xfer) { case CONFIG_FTDI_MODEM_CTRL: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - TU_ASSERT(ftdi_sio_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE),); - break; + p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + TU_ASSERT(ftdi_sio_set_modem_ctrl(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE),); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif case CONFIG_FTDI_SET_BAUDRATE: { @@ -1167,7 +1172,7 @@ static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { if (success) { switch(xfer->setup->bRequest) { case CP210X_SET_MHS: - p_cdc->line_state = (uint8_t) tu_le16toh(xfer->setup->wValue); + p_cdc->line_state = p_cdc->requested_line_state; break; case CP210X_SET_BAUDRATE: @@ -1207,9 +1212,9 @@ static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t comple return false; } -static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; - return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | line_state, NULL, 0, + return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | p_cdc->requested_line_state, NULL, 0, complete_cb ? cp210x_internal_control_complete : NULL, user_data); } @@ -1273,10 +1278,11 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { case CONFIG_CP210X_SET_DTR_RTS: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - TU_ASSERT(cp210x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, cp210x_process_config, CONFIG_CP210X_COMPLETE),); - break; + p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + TU_ASSERT(cp210x_set_modem_ctrl(p_cdc, cp210x_process_config, CONFIG_CP210X_COMPLETE),); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif case CONFIG_CP210X_COMPLETE: @@ -1399,19 +1405,7 @@ static void ch34x_internal_control_complete(tuh_xfer_t * xfer) { break; case CH34X_REQ_MODEM_CTRL: - // set modem controls RTS/DTR request. Note: signals are inverted - uint16_t const modem_signal = ~tu_le16toh(xfer->setup->wValue); - if (modem_signal & CH34X_BIT_RTS) { - p_cdc->line_state |= CDC_CONTROL_LINE_STATE_RTS; - } else { - p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_RTS; - } - - if (modem_signal & CH34X_BIT_DTR) { - p_cdc->line_state |= CDC_CONTROL_LINE_STATE_DTR; - } else { - p_cdc->line_state &= (uint8_t) ~CDC_CONTROL_LINE_STATE_DTR; - } + p_cdc->line_state = p_cdc->requested_line_state; break; default: break; @@ -1487,13 +1481,12 @@ static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complet return true; } -static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, uint16_t line_state, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint8_t control = 0; - if (line_state & CDC_CONTROL_LINE_STATE_RTS) { + if (p_cdc->requested_line_state & CDC_CONTROL_LINE_STATE_RTS) { control |= CH34X_BIT_RTS; } - if (line_state & CDC_CONTROL_LINE_STATE_DTR) { + if (p_cdc->requested_line_state & CDC_CONTROL_LINE_STATE_DTR) { control |= CH34X_BIT_DTR; } @@ -1587,7 +1580,8 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { case CONFIG_CH34X_MODEM_CONTROL: // !always! set modem controls RTS/DTR (CH34x has no reset state after CH34X_REQ_SERIAL_INIT) - TU_ASSERT (ch34x_set_modem_ctrl(p_cdc, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, ch34x_process_config, CONFIG_CH34X_COMPLETE),); + p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + TU_ASSERT (ch34x_set_modem_ctrl(p_cdc, ch34x_process_config, CONFIG_CH34X_COMPLETE),); break; case CONFIG_CH34X_COMPLETE: From dcadf8c2a2a79b838cfccf32612fadcb15216c77 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 22 Feb 2024 15:04:24 +0100 Subject: [PATCH 007/382] created set_function_call() --- src/class/cdc/cdc_host.c | 110 +++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 62 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 0af429e4b..6a650071d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -421,115 +421,101 @@ bool tuh_cdc_read_clear (uint8_t idx) { // Control Endpoint API //--------------------------------------------------------------------+ -bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t* p_cdc = get_itf(idx); - TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set control line state line_state = %u", line_state); - cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; - - p_cdc->requested_line_state = (uint8_t) line_state; - +// call of (non-)blocking set-functions (to set line state, baudrate, ...) +static bool set_function_call ( + cdch_interface_t * p_cdc, + bool (*set_function)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data), + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { if (complete_cb) { - return driver->set_control_line_state(p_cdc, complete_cb, user_data); + // non-blocking with call back + return set_function(p_cdc, complete_cb, user_data); } else { // blocking - xfer_result_t result = XFER_RESULT_INVALID; - bool ret = driver->set_control_line_state(p_cdc, complete_cb, (uintptr_t) &result); + xfer_result_t result = XFER_RESULT_INVALID; // use local result, because user_data ptr may be NULL + bool ret = set_function(p_cdc, NULL, (uintptr_t) &result); if (user_data) { - // user_data is not NULL, return result via user_data - *((xfer_result_t*) user_data) = result; + *((xfer_result_t *) user_data) = result; } - TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); - p_cdc->line_state = (uint8_t) line_state; - return true; + return (ret && result == XFER_RESULT_SUCCESS); } } +bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + cdch_interface_t * p_cdc = get_itf(idx); + TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + TU_LOG_P_CDC("set control line state line_state = %u", line_state); + cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; + + p_cdc->requested_line_state = (uint8_t) line_state; + + bool ret = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data); + + if (ret && !complete_cb) { + p_cdc->line_state = (uint8_t) line_state; + } + + return ret; +} + bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); TU_LOG_P_CDC("set baudrate = %lu", baudrate); - cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; + cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line_coding.bit_rate = baudrate; - if (complete_cb) { - return driver->set_baudrate(p_cdc, complete_cb, user_data); - } else { - // blocking - xfer_result_t result = XFER_RESULT_INVALID; - bool ret = driver->set_baudrate(p_cdc, complete_cb, (uintptr_t) &result); + bool ret = set_function_call(p_cdc, driver->set_baudrate, complete_cb, user_data); - if (user_data) { - // user_data is not NULL, return result via user_data - *((xfer_result_t*) user_data) = result; - } - - TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); + if (ret && !complete_cb) { p_cdc->line_coding.bit_rate = baudrate; - return true; } + + return ret; } bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); TU_LOG_P_CDC("set data format data_bits = %u parity = %u stop_bits = %u (indexes!)", data_bits, parity, stop_bits); - cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; + cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line_coding.stop_bits = stop_bits; p_cdc->requested_line_coding.parity = parity; p_cdc->requested_line_coding.data_bits = data_bits; - if (complete_cb) { - return driver->set_data_format(p_cdc, complete_cb, user_data); - } else { - // blocking - xfer_result_t result = XFER_RESULT_INVALID; - bool ret = driver->set_data_format(p_cdc, complete_cb, (uintptr_t) &result); + bool ret = set_function_call(p_cdc, driver->set_data_format, complete_cb, user_data); - if (user_data) { - // user_data is not NULL, return result via user_data - *((xfer_result_t*) user_data) = result; - } - - TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); + if (ret && !complete_cb) { p_cdc->line_coding.stop_bits = stop_bits; p_cdc->line_coding.parity = parity; p_cdc->line_coding.data_bits = data_bits; - return true; } + + return ret; } -bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t* p_cdc = get_itf(idx); +bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const * line_coding, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); TU_LOG_P_CDC("set line coding baudrate = %lu data_bits = %u parity = %u stop_bits = %u (indexes!)", line_coding->bit_rate, line_coding->data_bits, line_coding->parity, line_coding->stop_bits); - cdch_serial_driver_t const* driver = &serial_drivers[p_cdc->serial_drid]; + cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line_coding = *line_coding; - if ( complete_cb ) { - return driver->set_line_coding(p_cdc, complete_cb, user_data); - } else { - // blocking - xfer_result_t result = XFER_RESULT_INVALID; - bool ret = driver->set_line_coding(p_cdc, complete_cb, (uintptr_t) &result); + bool ret = set_function_call(p_cdc, driver->set_line_coding, complete_cb, user_data); - if (user_data) { - // user_data is not NULL, return result via user_data - *((xfer_result_t*) user_data) = result; - } - - TU_VERIFY(ret && result == XFER_RESULT_SUCCESS); + if (ret && !complete_cb) { p_cdc->line_coding = *line_coding; - return true; } + + return ret; } //--------------------------------------------------------------------+ From ea86bbe5f742344b307e52945c0977143522810b Mon Sep 17 00:00:00 2001 From: IngHK Date: Wed, 21 Feb 2024 16:30:02 +0100 Subject: [PATCH 008/382] added continue enum after config fail --- src/class/cdc/cdc_host.c | 109 ++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 42 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 6a650071d..226f389e3 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -47,6 +47,16 @@ #define TU_LOG_P_CDC(TXT,...) TU_LOG_CDC(TXT, p_cdc->daddr, p_cdc->bInterfaceNumber, \ serial_drivers[p_cdc->serial_drid].name, ##__VA_ARGS__) +#define TU_ASSERT_COMPLETE_DEFINE(_cond, _itf_offset) \ + do { \ + if (!(_cond)) { _MESS_FAILED(); TU_BREAKPOINT(); set_config_complete(idx, _itf_offset, false); } \ + } while(0) + +#define TU_ASSERT_COMPLETE_1ARGS(_cond) TU_ASSERT_COMPLETE_DEFINE(_cond, 0) +#define TU_ASSERT_COMPLETE_2ARGS(_cond, _itf_offset) TU_ASSERT_COMPLETE_DEFINE(_cond, _itf_offset) + +#define TU_ASSERT_COMPLETE(...) _GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_COMPLETE_2ARGS, TU_ASSERT_COMPLETE_1ARGS, _dummy)(__VA_ARGS__) + //--------------------------------------------------------------------+ // Host CDC Interface //--------------------------------------------------------------------+ @@ -285,7 +295,6 @@ static cdch_interface_t* make_new_itf(uint8_t daddr, tusb_desc_interface_t const } static bool open_ep_stream_pair(cdch_interface_t* p_cdc , tusb_desc_endpoint_t const *desc_ep); -static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num); //--------------------------------------------------------------------+ // APPLICATION API @@ -657,16 +666,26 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d return false; } -static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num) { - TU_LOG_P_CDC("set config complete"); - p_cdc->mounted = true; - if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(idx); +static void set_config_complete(uint8_t idx, uint8_t itf_offset, bool success) { + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); + TU_LOG_P_CDC("set config complete success = %u", success); - // Prepare for incoming data - tu_edpt_stream_read_xfer(&p_cdc->stream.rx); + if (success) { + p_cdc->mounted = true; + if (tuh_cdc_mount_cb) { + tuh_cdc_mount_cb(idx); + } + // Prepare for incoming data + tu_edpt_stream_read_xfer(&p_cdc->stream.rx); + } else { + // clear the interface entry + p_cdc->daddr = 0; + p_cdc->bInterfaceNumber = 0; + } // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(p_cdc->daddr, itf_num); + usbh_driver_set_config_complete(p_cdc->daddr, p_cdc->bInterfaceNumber + itf_offset); } bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { @@ -856,14 +875,14 @@ static void acm_process_config(tuh_xfer_t* xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t* p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); + TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS, 1); switch (state) { case CONFIG_ACM_SET_CONTROL_LINE_STATE: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM if (p_cdc->acm_capability.support_line_request) { p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT(acm_set_control_line_state(p_cdc, acm_process_config, CONFIG_ACM_SET_LINE_CODING),); + TU_ASSERT_COMPLETE(acm_set_control_line_state(p_cdc, acm_process_config, CONFIG_ACM_SET_LINE_CODING), 1); break; } #endif @@ -873,7 +892,7 @@ static void acm_process_config(tuh_xfer_t* xfer) { #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM if (p_cdc->acm_capability.support_line_request) { p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(acm_set_line_coding(p_cdc, acm_process_config, CONFIG_ACM_COMPLETE),); + TU_ASSERT_COMPLETE(acm_set_line_coding(p_cdc, acm_process_config, CONFIG_ACM_COMPLETE), 1); break; } #endif @@ -881,10 +900,11 @@ static void acm_process_config(tuh_xfer_t* xfer) { case CONFIG_ACM_COMPLETE: // itf_num+1 to account for data interface as well - set_config_complete(p_cdc, idx, itf_num + 1); + set_config_complete(idx, 1, true); break; default: + set_config_complete(idx, 1, false); break; } } @@ -1024,18 +1044,18 @@ static void ftdi_process_config(tuh_xfer_t* xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); + TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS); switch(state) { // Note may need to read FTDI eeprom case CONFIG_FTDI_RESET: - TU_ASSERT(ftdi_sio_reset(p_cdc, ftdi_process_config, CONFIG_FTDI_MODEM_CTRL),); + TU_ASSERT_COMPLETE(ftdi_sio_reset(p_cdc, ftdi_process_config, CONFIG_FTDI_MODEM_CTRL)); break; case CONFIG_FTDI_MODEM_CTRL: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT(ftdi_sio_set_modem_ctrl(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE),); + TU_ASSERT_COMPLETE(ftdi_sio_set_modem_ctrl(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE)); break; #else TU_ATTR_FALLTHROUGH; @@ -1044,7 +1064,7 @@ static void ftdi_process_config(tuh_xfer_t* xfer) { case CONFIG_FTDI_SET_BAUDRATE: { #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->requested_line_coding.bit_rate = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM).bit_rate; - TU_ASSERT(ftdi_sio_set_baudrate(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_DATA),); + TU_ASSERT_COMPLETE(ftdi_sio_set_baudrate(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_DATA)); break; #else TU_ATTR_FALLTHROUGH; @@ -1055,7 +1075,7 @@ static void ftdi_process_config(tuh_xfer_t* xfer) { #if 0 // TODO set data format #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(ftdi_sio_set_data(p_cdc, process_ftdi_config, CONFIG_FTDI_COMPLETE),); + TU_ASSERT_COMPLETE(ftdi_sio_set_data(p_cdc, process_ftdi_config, CONFIG_FTDI_COMPLETE)); break; #endif #endif @@ -1064,10 +1084,11 @@ static void ftdi_process_config(tuh_xfer_t* xfer) { } case CONFIG_FTDI_COMPLETE: - set_config_complete(p_cdc, idx, itf_num); + set_config_complete(idx, 0, true); break; default: + set_config_complete(idx, 0, false); break; } } @@ -1150,8 +1171,8 @@ static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfe static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); + cdch_interface_t* p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); TU_LOG_P_CDC("control complete success = %u", success); @@ -1236,17 +1257,17 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); + TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS); switch (state) { case CONFIG_CP210X_IFC_ENABLE: - TU_ASSERT(cp210x_ifc_enable(p_cdc, 1, cp210x_process_config, CONFIG_CP210X_SET_BAUDRATE),); + TU_ASSERT_COMPLETE(cp210x_ifc_enable(p_cdc, 1, cp210x_process_config, CONFIG_CP210X_SET_BAUDRATE)); break; case CONFIG_CP210X_SET_BAUDRATE: { #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->requested_line_coding.bit_rate = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM).bit_rate; - TU_ASSERT(cp210x_set_baudrate(p_cdc, cp210x_process_config, CONFIG_CP210X_SET_LINE_CTL),); + TU_ASSERT_COMPLETE(cp210x_set_baudrate(p_cdc, cp210x_process_config, CONFIG_CP210X_SET_LINE_CTL)); break; #else TU_ATTR_FALLTHROUGH; @@ -1265,17 +1286,19 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { case CONFIG_CP210X_SET_DTR_RTS: #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT(cp210x_set_modem_ctrl(p_cdc, cp210x_process_config, CONFIG_CP210X_COMPLETE),); + TU_ASSERT_COMPLETE(cp210x_set_modem_ctrl(p_cdc, cp210x_process_config, CONFIG_CP210X_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; #endif case CONFIG_CP210X_COMPLETE: - set_config_complete(p_cdc, idx, itf_num); + set_config_complete(idx, 0, true); break; - default: break; + default: + set_config_complete(idx, 0, false); + break; } } @@ -1361,11 +1384,11 @@ static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t comp // internal control complete to update state such as line state, encoding static void ch34x_internal_control_complete(tuh_xfer_t * xfer) { - // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber + // CH34x only has 1 interface and wIndex used as payload and not for bInterfaceNumber uint8_t const itf_num = 0; uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); + cdch_interface_t* p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); TU_LOG_P_CDC("control complete success = %u", success); @@ -1526,14 +1549,14 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { uint8_t const itf_num = 0; uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t* p_cdc = get_itf(idx); + TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS); uintptr_t const state = xfer->user_data; uint8_t buffer[2]; // TODO remove - TU_ASSERT (p_cdc,); - TU_ASSERT (xfer->result == XFER_RESULT_SUCCESS,); switch (state) { case CONFIG_CH34X_READ_VERSION: - TU_ASSERT (ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, ch34x_process_config, CONFIG_CH34X_SERIAL_INIT),); + TU_ASSERT_COMPLETE(ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, + ch34x_process_config, CONFIG_CH34X_SERIAL_INIT)); break; case CONFIG_CH34X_SERIAL_INIT: { @@ -1541,41 +1564,43 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { uint8_t const version = xfer->buffer[0]; TU_LOG_P_CDC("Chip Version = %02x", version); // only versions >= 0x30 are tested, below 0x30 seems having other programming, see drivers from WCH vendor, Linux kernel and FreeBSD - TU_ASSERT (version >= 0x30,); + TU_ASSERT_COMPLETE(version >= 0x30); // init CH34x with line coding p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc); - TU_ASSERT(div_ps, ); + TU_ASSERT_COMPLETE(div_ps); uint8_t const lcr = ch34x_get_lcr(p_cdc); - TU_ASSERT(lcr, ); - TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, tu_u16(lcr, 0x9c), div_ps, - ch34x_process_config, CONFIG_CH34X_SPECIAL_REG_WRITE),); + TU_ASSERT_COMPLETE(lcr); + TU_ASSERT_COMPLETE(ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, tu_u16(lcr, 0x9c), div_ps, + ch34x_process_config, CONFIG_CH34X_SPECIAL_REG_WRITE)); break; } case CONFIG_CH34X_SPECIAL_REG_WRITE: // overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver p_cdc->line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; - TU_ASSERT (ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL),); + TU_ASSERT_COMPLETE(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, + ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL)); break; case CONFIG_CH34X_FLOW_CONTROL: // no hardware flow control - TU_ASSERT (ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x27, CH341_REG_0x27), 0x0000, ch34x_process_config, CONFIG_CH34X_MODEM_CONTROL),); + TU_ASSERT_COMPLETE(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x27, CH341_REG_0x27), 0x0000, + ch34x_process_config, CONFIG_CH34X_MODEM_CONTROL)); break; case CONFIG_CH34X_MODEM_CONTROL: // !always! set modem controls RTS/DTR (CH34x has no reset state after CH34X_REQ_SERIAL_INIT) p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT (ch34x_set_modem_ctrl(p_cdc, ch34x_process_config, CONFIG_CH34X_COMPLETE),); + TU_ASSERT_COMPLETE(ch34x_set_modem_ctrl(p_cdc, ch34x_process_config, CONFIG_CH34X_COMPLETE)); break; case CONFIG_CH34X_COMPLETE: - set_config_complete(p_cdc, idx, itf_num); + set_config_complete(idx, 0, true); break; default: - TU_ASSERT (false,); + set_config_complete(idx, 0, false); break; } } From 22a12c76689399bd1a67e52531171876e5d88a28 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 22 Feb 2024 09:28:06 +0100 Subject: [PATCH 009/382] improved ACM checks --- src/class/cdc/cdc_host.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 226f389e3..ae8245b0e 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -773,6 +773,11 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, tuh_xfer_cb_t co } static bool acm_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_VERIFY(p_cdc->acm_capability.support_line_request); + TU_VERIFY(p_cdc->requested_line_coding.data_bits && p_cdc->requested_line_coding.bit_rate); + TU_VERIFY((p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8) || + p_cdc->requested_line_coding.data_bits == 16); + tusb_control_request_t const request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, @@ -813,7 +818,6 @@ static bool acm_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, p_cdc->requested_line_coding.stop_bits = p_cdc->line_coding.stop_bits; p_cdc->requested_line_coding.parity = p_cdc->line_coding.parity; p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits; - TU_VERIFY(p_cdc->acm_capability.support_line_request); return acm_set_line_coding(p_cdc, complete_cb, user_data); } From 138567af3e39e08742b3d1edf5b83d27d8526a4a Mon Sep 17 00:00:00 2001 From: IngHK Date: Sun, 18 Feb 2024 20:33:54 +0100 Subject: [PATCH 010/382] fixed #2448 CH34x ch34x_set_line_coding() callback bug --- src/class/cdc/cdc_host.c | 135 +++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 56 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index ae8245b0e..f6804ca2b 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -80,6 +80,9 @@ typedef struct { uint8_t requested_line_state; tuh_xfer_cb_t user_control_cb; + #if CFG_TUH_CDC_CH34X + tuh_xfer_cb_t requested_complete_cb; + #endif struct { tu_edpt_stream_t tx; @@ -1376,12 +1379,33 @@ static inline bool ch34x_write_reg(cdch_interface_t* p_cdc, uint16_t reg, uint16 // return ch34x_control_in ( p_cdc, CH34X_REQ_READ_REG, reg, 0, buffer, buffersize, complete_cb, user_data ); //} -static bool ch34x_write_reg_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ch34x_write_reg_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint8_t const lcr = ch34x_get_lcr(p_cdc); + TU_VERIFY(lcr); + + return ch34x_write_reg(p_cdc, CH32X_REG16_LCR2_LCR, lcr, complete_cb, user_data); +} + +static bool ch34x_write_reg_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc); TU_VERIFY(div_ps); - TU_ASSERT(ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, - complete_cb, user_data)); - return true; + + return ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, complete_cb, user_data); +} + +static bool ch34x_modem_ctrl_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint8_t control = 0; + if (p_cdc->requested_line_state & CDC_CONTROL_LINE_STATE_RTS) { + control |= CH34X_BIT_RTS; + } + if (p_cdc->requested_line_state & CDC_CONTROL_LINE_STATE_DTR) { + control |= CH34X_BIT_DTR; + } + + // CH34x signals are inverted + control = ~control; + + return ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, complete_cb, user_data); } //------------- Driver API -------------// @@ -1431,34 +1455,34 @@ static void ch34x_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool ch34x_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t const lcr = ch34x_get_lcr(p_cdc); - TU_VERIFY(lcr); - TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, CH32X_REG16_LCR2_LCR, lcr, - complete_cb ? ch34x_internal_control_complete : NULL, user_data)); +static bool ch34x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->user_control_cb = complete_cb; + TU_ASSERT(ch34x_write_reg_data_format(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); + return true; } -static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ch34x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); + return true; } -static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) { - // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber +static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t * xfer) { + // CH34x only has 1 interface and wIndex used as payload and not for bInterfaceNumber uint8_t const itf_num = 0; uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t* p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); if (xfer->result == XFER_RESULT_SUCCESS) { - // stage 1 success, continue to stage 2 - p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; - TU_ASSERT(ch34x_set_data_format(p_cdc, ch34x_internal_control_complete, xfer->user_data), ); + // stage 1 success, continue with stage 2 + p_cdc->user_control_cb = p_cdc->requested_complete_cb; + ch34x_write_reg_data_format(p_cdc, ch34x_internal_control_complete, xfer->user_data); } else { // stage 1 failed, notify user - xfer->complete_cb = p_cdc->user_control_cb; + xfer->complete_cb = p_cdc->requested_complete_cb; if (xfer->complete_cb) { xfer->complete_cb(xfer); } @@ -1466,49 +1490,46 @@ static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t* xfer) { } // 2 stages: set baudrate (stage1) + set data format (stage2) -static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_control_cb = complete_cb; - +static bool ch34x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { if (complete_cb) { // stage 1 set baudrate - TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, ch34x_set_line_coding_stage1_complete, user_data)); + p_cdc->requested_complete_cb = complete_cb; + p_cdc->user_control_cb = ch34x_set_line_coding_stage1_complete; + return ch34x_write_reg_baudrate(p_cdc, ch34x_internal_control_complete, user_data); } else { - // sync call - xfer_result_t result; - + // blocking sequence // stage 1 set baudrate - TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, NULL, (uintptr_t) &result)); - TU_VERIFY(result == XFER_RESULT_SUCCESS); - p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + xfer_result_t result = XFER_RESULT_INVALID; // use local result, because user_data ptr may be NULL + bool ret = ch34x_write_reg_baudrate(p_cdc, NULL, (uintptr_t) &result); - // stage 2 set data format - TU_ASSERT(ch34x_set_data_format(p_cdc, NULL, (uintptr_t) &result)); - TU_VERIFY(result == XFER_RESULT_SUCCESS); - - // update transfer result, user_data is expected to point to xfer_result_t + // store/check results if (user_data) { *((xfer_result_t*) user_data) = result; } - } + TU_ASSERT(ret); + TU_VERIFY(result == XFER_RESULT_SUCCESS); - return true; + // overtake baudrate + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + + // stage 2 set data format + result = XFER_RESULT_INVALID; + ret = ch34x_write_reg_data_format(p_cdc, NULL, (uintptr_t) &result); + + // store/check results + if (user_data) { + *((xfer_result_t*) user_data) = result; + } + TU_ASSERT(ret); + return (result == XFER_RESULT_SUCCESS); + // the overtaking of remaining requested_line_coding will be done in tuh_cdc_set_line_coding() + } } -static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t control = 0; - if (p_cdc->requested_line_state & CDC_CONTROL_LINE_STATE_RTS) { - control |= CH34X_BIT_RTS; - } - if (p_cdc->requested_line_state & CDC_CONTROL_LINE_STATE_DTR) { - control |= CH34X_BIT_DTR; - } - - // CH34x signals are inverted - control = ~control; - +static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; - TU_ASSERT (ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, - complete_cb ? ch34x_internal_control_complete : NULL, user_data)); + TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); + return true; } @@ -1549,25 +1570,27 @@ static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uin } static void ch34x_process_config(tuh_xfer_t* xfer) { - // CH34x only has 1 interface and use wIndex as payload and not for bInterfaceNumber + // CH34x only has 1 interface and wIndex used as payload and not for bInterfaceNumber + uintptr_t const state = xfer->user_data; uint8_t const itf_num = 0; uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t* p_cdc = get_itf(idx); TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS); - uintptr_t const state = xfer->user_data; uint8_t buffer[2]; // TODO remove switch (state) { case CONFIG_CH34X_READ_VERSION: + p_cdc->user_control_cb = ch34x_process_config; // set once for whole process config TU_ASSERT_COMPLETE(ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, - ch34x_process_config, CONFIG_CH34X_SERIAL_INIT)); + ch34x_process_config, CONFIG_CH34X_SERIAL_INIT)); break; case CONFIG_CH34X_SERIAL_INIT: { // handle version read data, set CH34x line coding (incl. baudrate) uint8_t const version = xfer->buffer[0]; TU_LOG_P_CDC("Chip Version = %02x", version); - // only versions >= 0x30 are tested, below 0x30 seems having other programming, see drivers from WCH vendor, Linux kernel and FreeBSD + // only versions >= 0x30 are tested, below 0x30 seems having other programming + // see drivers from WCH vendor, Linux kernel and FreeBSD TU_ASSERT_COMPLETE(version >= 0x30); // init CH34x with line coding p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; @@ -1584,19 +1607,19 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { // overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver p_cdc->line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; TU_ASSERT_COMPLETE(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, - ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL)); + ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL)); break; case CONFIG_CH34X_FLOW_CONTROL: // no hardware flow control TU_ASSERT_COMPLETE(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x27, CH341_REG_0x27), 0x0000, - ch34x_process_config, CONFIG_CH34X_MODEM_CONTROL)); + ch34x_process_config, CONFIG_CH34X_MODEM_CONTROL)); break; case CONFIG_CH34X_MODEM_CONTROL: // !always! set modem controls RTS/DTR (CH34x has no reset state after CH34X_REQ_SERIAL_INIT) p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT_COMPLETE(ch34x_set_modem_ctrl(p_cdc, ch34x_process_config, CONFIG_CH34X_COMPLETE)); + TU_ASSERT_COMPLETE(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE)); break; case CONFIG_CH34X_COMPLETE: @@ -1668,7 +1691,7 @@ static uint8_t ch34x_get_lcr(cdch_interface_t * p_cdc) { uint8_t const data_bits = p_cdc->requested_line_coding.data_bits; uint8_t lcr = CH34X_LCR_ENABLE_RX | CH34X_LCR_ENABLE_TX; - TU_VERIFY(data_bits >= 5 && data_bits <= 8, 0); + TU_VERIFY(data_bits >= 5 && data_bits <= 8); lcr |= (uint8_t) (data_bits - 5); switch(parity) { @@ -1695,7 +1718,7 @@ static uint8_t ch34x_get_lcr(cdch_interface_t * p_cdc) { } // 1.5 stop bits not supported - TU_VERIFY(stop_bits != CDC_LINE_CODING_STOP_BITS_1_5, 0); + TU_VERIFY(stop_bits != CDC_LINE_CODING_STOP_BITS_1_5); if (stop_bits == CDC_LINE_CODING_STOP_BITS_2) { lcr |= CH34X_LCR_STOP_BITS_2; } From db511fb2f3df190f538d84d08b6be83746adae0e Mon Sep 17 00:00:00 2001 From: IngHK Date: Mon, 19 Feb 2024 08:05:16 +0100 Subject: [PATCH 011/382] fixed CFG_TUH_CDC_LINE_CONTROL_ON_ENUM handling. only set if defined. value 0 is also valid --- src/class/cdc/cdc_host.c | 17 ++++++++++------- src/class/cdc/cdc_host.h | 10 ---------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index f6804ca2b..850c1fceb 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -886,7 +886,7 @@ static void acm_process_config(tuh_xfer_t* xfer) { switch (state) { case CONFIG_ACM_SET_CONTROL_LINE_STATE: - #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM if (p_cdc->acm_capability.support_line_request) { p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(acm_set_control_line_state(p_cdc, acm_process_config, CONFIG_ACM_SET_LINE_CODING), 1); @@ -1060,7 +1060,7 @@ static void ftdi_process_config(tuh_xfer_t* xfer) { break; case CONFIG_FTDI_MODEM_CTRL: - #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(ftdi_sio_set_modem_ctrl(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE)); break; @@ -1291,7 +1291,7 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { } case CONFIG_CP210X_SET_DTR_RTS: - #if CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(cp210x_set_modem_ctrl(p_cdc, cp210x_process_config, CONFIG_CP210X_COMPLETE)); break; @@ -1617,10 +1617,13 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { break; case CONFIG_CH34X_MODEM_CONTROL: - // !always! set modem controls RTS/DTR (CH34x has no reset state after CH34X_REQ_SERIAL_INIT) - p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT_COMPLETE(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE)); - break; + #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + TU_ASSERT_COMPLETE(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE)); + break; + #else + TU_ATTR_FALLTHROUGH; + #endif case CONFIG_CH34X_COMPLETE: set_config_complete(idx, 0, true); diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index d512a23a5..ca6567453 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -37,16 +37,6 @@ // Class Driver Configuration //--------------------------------------------------------------------+ -// Set Line Control state on enumeration/mounted: DTR ( bit 0), RTS (bit 1) -#ifndef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM -#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0 -#endif - -// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t -//#ifndef CFG_TUH_CDC_LINE_CODING_ON_ENUM -//#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } -//#endif - // RX FIFO size #ifndef CFG_TUH_CDC_RX_BUFSIZE #define CFG_TUH_CDC_RX_BUFSIZE USBH_EPSIZE_BULK_MAX From 0b5f85eee0f34a80dd8debe2f764607070293119 Mon Sep 17 00:00:00 2001 From: IngHK Date: Wed, 21 Feb 2024 17:25:13 +0100 Subject: [PATCH 012/382] created set_line_coding_sequence() and void set_line_coding_stage1_complete() to be reused by FTDI & CP210x --- src/class/cdc/cdc_host.c | 131 ++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 50 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 850c1fceb..8deeffc37 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -433,6 +433,77 @@ bool tuh_cdc_read_clear (uint8_t idx) { // Control Endpoint API //--------------------------------------------------------------------+ +// set line coding using sequence with 2 stages: set baudrate (stage1) + set data format (stage2) +static bool set_line_coding_sequence( + cdch_interface_t * p_cdc, + // control request function to set baudrate + bool (*set_baudrate_request)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data), + // control request function to set data format + bool (*set_data_format_request)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data), + // function to be called after stage 1 completed + void (*set_line_coding_stage1_complete)(tuh_xfer_t * xfer), + // control complete function to be called after request + void (*internal_control_complete)(tuh_xfer_t * xfer), + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + if (complete_cb) { + // non-blocking + // stage 1 set baudrate + p_cdc->requested_complete_cb = complete_cb; // store complete_cb to be used in set_line_coding_stage1_complete() + p_cdc->user_control_cb = set_line_coding_stage1_complete; + return set_baudrate_request(p_cdc, internal_control_complete, user_data); + } else { + // blocking sequence + // stage 1 set baudrate + xfer_result_t result = XFER_RESULT_INVALID; // use local result, because user_data ptr may be NULL + bool ret = set_baudrate_request(p_cdc, NULL, (uintptr_t) &result); + + if (user_data) { + *((xfer_result_t *) user_data) = result; + } + + TU_ASSERT(ret); + TU_VERIFY(result == XFER_RESULT_SUCCESS); + + // overtake baudrate after successful request + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + + // stage 2 set data format + result = XFER_RESULT_INVALID; + ret = set_data_format_request(p_cdc, NULL, (uintptr_t) &result); + + if (user_data) { + *((xfer_result_t *) user_data) = result; + } + + TU_ASSERT(ret); + return (result == XFER_RESULT_SUCCESS); + // the overtaking of remaining requested_line_coding will be done in tuh_cdc_set_line_coding() + } +} + +static void set_line_coding_stage1_complete( + tuh_xfer_t * xfer, uint8_t const itf_num, + // control request function to set data format + bool (*set_data_format_request)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data), + // control complete function to be called after request + void (*internal_control_complete)(tuh_xfer_t * xfer)) { + uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); + + if (xfer->result == XFER_RESULT_SUCCESS) { + // stage 1 success, continue with stage 2 + p_cdc->user_control_cb = p_cdc->requested_complete_cb; + set_data_format_request(p_cdc, internal_control_complete, xfer->user_data); + } else { + // stage 1 failed, notify user + xfer->complete_cb = p_cdc->requested_complete_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } + } +} + // call of (non-)blocking set-functions (to set line state, baudrate, ...) static bool set_function_call ( cdch_interface_t * p_cdc, @@ -1470,60 +1541,20 @@ static bool ch34x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_ } static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t * xfer) { - // CH34x only has 1 interface and wIndex used as payload and not for bInterfaceNumber - uint8_t const itf_num = 0; - uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t* p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - - if (xfer->result == XFER_RESULT_SUCCESS) { - // stage 1 success, continue with stage 2 - p_cdc->user_control_cb = p_cdc->requested_complete_cb; - ch34x_write_reg_data_format(p_cdc, ch34x_internal_control_complete, xfer->user_data); - } else { - // stage 1 failed, notify user - xfer->complete_cb = p_cdc->requested_complete_cb; - if (xfer->complete_cb) { - xfer->complete_cb(xfer); - } - } + uint8_t const itf_num = 0; // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber + set_line_coding_stage1_complete(xfer, itf_num, + ch34x_write_reg_data_format, // control request function to set data format + ch34x_internal_control_complete); // control complete function to be called after request } // 2 stages: set baudrate (stage1) + set data format (stage2) static bool ch34x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - if (complete_cb) { - // stage 1 set baudrate - p_cdc->requested_complete_cb = complete_cb; - p_cdc->user_control_cb = ch34x_set_line_coding_stage1_complete; - return ch34x_write_reg_baudrate(p_cdc, ch34x_internal_control_complete, user_data); - } else { - // blocking sequence - // stage 1 set baudrate - xfer_result_t result = XFER_RESULT_INVALID; // use local result, because user_data ptr may be NULL - bool ret = ch34x_write_reg_baudrate(p_cdc, NULL, (uintptr_t) &result); - - // store/check results - if (user_data) { - *((xfer_result_t*) user_data) = result; - } - TU_ASSERT(ret); - TU_VERIFY(result == XFER_RESULT_SUCCESS); - - // overtake baudrate - p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; - - // stage 2 set data format - result = XFER_RESULT_INVALID; - ret = ch34x_write_reg_data_format(p_cdc, NULL, (uintptr_t) &result); - - // store/check results - if (user_data) { - *((xfer_result_t*) user_data) = result; - } - TU_ASSERT(ret); - return (result == XFER_RESULT_SUCCESS); - // the overtaking of remaining requested_line_coding will be done in tuh_cdc_set_line_coding() - } + return set_line_coding_sequence(p_cdc, + ch34x_write_reg_baudrate, // control request function to set baudrate + ch34x_write_reg_data_format, // control request function to set data format + ch34x_set_line_coding_stage1_complete, // function to be called after stage 1 completed + ch34x_internal_control_complete, // control complete function to be called after request + complete_cb, user_data); } static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { From 7fef5943eff0d7f1b7122e878cf2caa78bea06aa Mon Sep 17 00:00:00 2001 From: IngHK Date: Sat, 24 Feb 2024 12:58:45 +0100 Subject: [PATCH 013/382] improved FTDI support --- src/class/cdc/cdc_host.c | 529 ++++++++++++++++++++++++++------ src/class/cdc/serial/ftdi_sio.h | 371 +++++++++++----------- src/tusb_option.h | 19 +- 3 files changed, 622 insertions(+), 297 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 8deeffc37..f9540efbe 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -35,6 +35,9 @@ #include "host/usbh_pvt.h" #include "cdc_host.h" +#include "serial/ftdi_sio.h" +#include "serial/cp210x.h" +#include "serial/ch34x.h" // Level where CFG_TUSB_DEBUG must be at least for this driver is logged #ifndef CFG_TUH_CDC_LOG_LEVEL @@ -80,10 +83,14 @@ typedef struct { uint8_t requested_line_state; tuh_xfer_cb_t user_control_cb; - #if CFG_TUH_CDC_CH34X + #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CH34X tuh_xfer_cb_t requested_complete_cb; #endif + #if CFG_TUH_CDC_FTDI + ftdi_private_t ftdi; + #endif + struct { tu_edpt_stream_t tx; tu_edpt_stream_t rx; @@ -98,6 +105,9 @@ typedef struct { CFG_TUH_MEM_SECTION static cdch_interface_t cdch_data[CFG_TUH_CDC]; +#if CFG_TUH_CDC_FTDI + static tusb_desc_device_t desc_dev[CFG_TUH_CDC][CFG_TUH_ENUMERATION_BUFSIZE]; +#endif //--------------------------------------------------------------------+ // Serial Driver @@ -114,23 +124,22 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, tuh_xfer_cb_t co //------------- FTDI prototypes -------------// #if CFG_TUH_CDC_FTDI -#include "serial/ftdi_sio.h" - static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST}; +#if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL +static uint8_t const * ftdi_chip_name[] = { FTDI_CHIP_NAMES }; +#endif static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); static void ftdi_process_config(tuh_xfer_t* xfer); -static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ftdi_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif //------------- CP210X prototypes -------------// #if CFG_TUH_CDC_CP210X -#include "serial/cp210x.h" - static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIST}; static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); @@ -144,8 +153,6 @@ static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complet //------------- CH34x prototypes -------------// #if CFG_TUH_CDC_CH34X -#include "serial/ch34x.h" - static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST}; static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len); @@ -212,8 +219,8 @@ static const cdch_serial_driver_t serial_drivers[] = { .vid_pid_count = TU_ARRAY_SIZE(ftdi_vid_pid_list), .open = ftdi_open, .process_set_config = ftdi_process_config, - .set_control_line_state = ftdi_sio_set_modem_ctrl, - .set_baudrate = ftdi_sio_set_baudrate, + .set_control_line_state = ftdi_set_modem_ctrl, + .set_baudrate = ftdi_set_baudrate, .set_data_format = ftdi_set_data_format, .set_line_coding = ftdi_set_line_coding, #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL @@ -992,28 +999,27 @@ static void acm_process_config(tuh_xfer_t* xfer) { //--------------------------------------------------------------------+ #if CFG_TUH_CDC_FTDI -static uint32_t ftdi_232bm_baud_to_divisor(cdch_interface_t* p_cdc); +static bool ftdi_determine_type(cdch_interface_t * p_cdc, uint8_t const idx); +static uint32_t ftdi_get_divisor(cdch_interface_t * p_cdc); +static uint8_t ftdi_get_idx(tuh_xfer_t * xfer); //------------- Control Request -------------// // set request without data -static bool ftdi_sio_set_request(cdch_interface_t* p_cdc, uint8_t command, uint16_t value, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_VENDOR, - .direction = TUSB_DIR_OUT - }, - .bRequest = command, - .wValue = tu_htole16(value), - .wIndex = 0, - .wLength = 0 +static bool ftdi_set_request(cdch_interface_t * p_cdc, uint8_t request, uint8_t requesttype, + uint16_t value, uint16_t index, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + tusb_control_request_t const request_setup = { + .bmRequestType = requesttype, + .bRequest = request, + .wValue = tu_htole16(value), + .wIndex = tu_htole16(index), + .wLength = 0 }; tuh_xfer_t xfer = { .daddr = p_cdc->daddr, .ep_addr = 0, - .setup = &request, + .setup = &request_setup, .buffer = NULL, .complete_cb = complete_cb, .user_data = user_data @@ -1022,16 +1028,57 @@ static bool ftdi_sio_set_request(cdch_interface_t* p_cdc, uint8_t command, uint1 return tuh_control_xfer(&xfer); } -static bool ftdi_sio_reset(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return ftdi_sio_set_request(p_cdc, FTDI_SIO_RESET, FTDI_SIO_RESET_SIO, complete_cb, user_data); +#ifdef CFG_TUH_CDC_FTDI_LATENCY +static int8_t ftdi_write_latency_timer(cdch_interface_t * p_cdc, uint16_t latency, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + if (p_cdc->ftdi.chip_type == SIO /* || p_cdc->ftdi.chip_type == FT232A */ ) + return FTDI_NOT_POSSIBLE; + return ftdi_set_request(p_cdc, FTDI_SIO_SET_LATENCY_TIMER_REQUEST, FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, + latency, p_cdc->ftdi.channel, complete_cb, user_data) ? FTDI_REQUESTED : FTDI_FAIL; +} +#endif + +static inline bool ftdi_sio_reset(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return ftdi_set_request(p_cdc, FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, FTDI_SIO_RESET_SIO, + p_cdc->ftdi.channel, complete_cb, user_data); +} + +static bool ftdi_change_speed(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint32_t index_value = ftdi_get_divisor(p_cdc); + TU_VERIFY(index_value); + uint16_t value = (uint16_t) index_value; + uint16_t index = (uint16_t) (index_value >> 16); + if (p_cdc->ftdi.channel) { + index = (uint16_t)((index << 8) | p_cdc->ftdi.channel); + } + + return ftdi_set_request(p_cdc, FTDI_SIO_SET_BAUDRATE_REQUEST, FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, + value, index, complete_cb, user_data); +} + +static bool ftdi_set_data_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 7 && p_cdc->requested_line_coding.data_bits <= 8, 0); + uint16_t value = (uint16_t) ( + ((uint32_t) p_cdc->requested_line_coding.data_bits & 0xf) | // data bit quantity is stored in bits 0-3 + ((uint32_t) p_cdc->requested_line_coding.parity & 0x7) << 8 | // parity is stored in bits 8-10, same coding + ((uint32_t) p_cdc->requested_line_coding.stop_bits & 0x3) << 11 ); // stop bits quantity is stored in bits 11-12, same coding + // not each FTDI supports 1.5 stop bits + + return ftdi_set_request(p_cdc, FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, + value, p_cdc->ftdi.channel, complete_cb, user_data); +} + +static inline bool ftdi_update_mctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // FTDI has the same bit coding + return ftdi_set_request(p_cdc, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + p_cdc->requested_line_state, p_cdc->ftdi.channel, complete_cb, user_data); } //------------- Driver API -------------// // internal control complete to update state such as line state, line_coding static void ftdi_internal_control_complete(tuh_xfer_t * xfer) { - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + uint8_t const idx = ftdi_get_idx(xfer); cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); @@ -1039,11 +1086,17 @@ static void ftdi_internal_control_complete(tuh_xfer_t * xfer) { if (success) { switch (xfer->setup->bRequest) { - case FTDI_SIO_MODEM_CTRL: + case FTDI_SIO_SET_MODEM_CTRL_REQUEST: p_cdc->line_state = p_cdc->requested_line_state; break; - case FTDI_SIO_SET_BAUD_RATE: + case FTDI_SIO_SET_DATA_REQUEST: + p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; + p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; + p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; + break; + + case FTDI_SIO_SET_BAUDRATE_REQUEST: p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; break; @@ -1057,52 +1110,62 @@ static void ftdi_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool ftdi_sio_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint16_t const divisor = (uint16_t) ftdi_232bm_baud_to_divisor(p_cdc); - +static bool ftdi_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; - TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_SET_BAUD_RATE, divisor, - complete_cb ? ftdi_internal_control_complete : NULL, user_data)); + TU_ASSERT(ftdi_set_data_request(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); return true; } -static bool ftdi_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - (void) p_cdc; - (void) complete_cb; - (void) user_data; - // TODO not implemented yet - return false; -} - -static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - (void) p_cdc; - (void) complete_cb; - (void) user_data; - // TODO not implemented yet - return false; -} - -static bool ftdi_sio_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ftdi_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; - TU_ASSERT(ftdi_sio_set_request(p_cdc, FTDI_SIO_MODEM_CTRL, 0x0300 | p_cdc->requested_line_state, - complete_cb ? ftdi_internal_control_complete : NULL, user_data)); + TU_ASSERT(ftdi_change_speed(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); + + return true; +} + +static void ftdi_set_line_coding_stage1_complete(tuh_xfer_t * xfer) { + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + set_line_coding_stage1_complete(xfer, itf_num, + ftdi_set_data_request, // control request function to set data format + ftdi_internal_control_complete); // control complete function to be called after request +} + +// 2 stages: set baudrate (stage1) + set data format (stage2) +static bool ftdi_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return set_line_coding_sequence(p_cdc, + ftdi_change_speed, // control request function to set baudrate + ftdi_set_data_request, // control request function to set data format + ftdi_set_line_coding_stage1_complete, // function to be called after stage 1 completed + ftdi_internal_control_complete, // control complete function to be called after request + complete_cb, user_data); +} + +static bool ftdi_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->user_control_cb = complete_cb; + TU_ASSERT(ftdi_update_mctrl(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); + return true; } //------------- Enumeration -------------// enum { - CONFIG_FTDI_RESET = 0, - CONFIG_FTDI_MODEM_CTRL, - CONFIG_FTDI_SET_BAUDRATE, + CONFIG_FTDI_GET_DESC = 0, + CONFIG_FTDI_DETERMINE_TYPE, + CONFIG_FTDI_WRITE_LATENCY, + CONFIG_FTDI_SIO_RESET, CONFIG_FTDI_SET_DATA, + CONFIG_FTDI_SET_BAUDRATE, + CONFIG_FTDI_FLOW_CONTROL, + CONFIG_FTDI_MODEM_CTRL, CONFIG_FTDI_COMPLETE }; -static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { +static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len) { // FTDI Interface includes 1 vendor interface + 2 bulk endpoints - TU_VERIFY(itf_desc->bInterfaceSubClass == 0xff && itf_desc->bInterfaceProtocol == 0xff && itf_desc->bNumEndpoints == 2); + TU_VERIFY(itf_desc->bInterfaceSubClass == 0xff && itf_desc->bInterfaceProtocol == 0xff && + itf_desc->bNumEndpoints == 2); TU_VERIFY(sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) <= max_len); cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); @@ -1113,54 +1176,97 @@ static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint // endpoint pair tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + /* + * NOTE: Some customers have programmed FT232R/FT245R devices + * with an endpoint size of 0 - not good. + */ + TU_ASSERT(desc_ep->wMaxPacketSize != 0); + // data endpoints expected to be in pairs return open_ep_stream_pair(p_cdc, desc_ep); } -static void ftdi_process_config(tuh_xfer_t* xfer) { +static void ftdi_process_config(tuh_xfer_t * xfer) { uintptr_t const state = xfer->user_data; - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + uint8_t const idx = ftdi_get_idx(xfer); cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS); + uint8_t const itf_num = p_cdc->bInterfaceNumber; switch(state) { - // Note may need to read FTDI eeprom - case CONFIG_FTDI_RESET: - TU_ASSERT_COMPLETE(ftdi_sio_reset(p_cdc, ftdi_process_config, CONFIG_FTDI_MODEM_CTRL)); + + // from here sequence overtaken from Linux Kernel function ftdi_port_probe() + case CONFIG_FTDI_GET_DESC: + // get device descriptor + p_cdc->user_control_cb = ftdi_process_config; // set once for whole process config + if (itf_num == 0) { // only necessary for 1st interface. other interface overtake type from interface 0 + TU_ASSERT_COMPLETE(tuh_descriptor_get_device(xfer->daddr, desc_dev[idx], sizeof(tusb_desc_device_t), + ftdi_process_config, CONFIG_FTDI_DETERMINE_TYPE)); + break; + } + TU_ATTR_FALLTHROUGH; + + case CONFIG_FTDI_DETERMINE_TYPE: + // determine type + if (itf_num == 0) { + TU_ASSERT_COMPLETE(ftdi_determine_type(p_cdc, idx)); + } else { + // other interfaces have same type as interface 0 + uint8_t const idx_itf0 = tuh_cdc_itf_get_index(xfer->daddr, 0); + cdch_interface_t const * p_cdc_itf0 = get_itf(idx_itf0); + p_cdc->ftdi.chip_type = p_cdc_itf0->ftdi.chip_type; + } + TU_ATTR_FALLTHROUGH; + + case CONFIG_FTDI_WRITE_LATENCY: + #ifdef CFG_TUH_CDC_FTDI_LATENCY + int8_t result = ftdi_write_latency_timer(p_cdc, CFG_TUH_CDC_FTDI_LATENCY, ftdi_process_config, + CONFIG_FTDI_SIO_RESET); + TU_ASSERT_COMPLETE(result != FTDI_FAIL); + if(result == FTDI_REQUESTED) { + break; + } // else FTDI_NOT_POSSIBLE => continue directly with next state + #endif + TU_ATTR_FALLTHROUGH; + + // from here sequence overtaken from Linux Kernel function ftdi_open() + case CONFIG_FTDI_SIO_RESET: + TU_ASSERT_COMPLETE(ftdi_sio_reset(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_DATA)); + break; + + // from here sequence overtaken from Linux Kernel function ftdi_set_termios() + case CONFIG_FTDI_SET_DATA: + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + TU_ASSERT_COMPLETE(ftdi_set_data_request(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_SET_BAUDRATE)); + break; + #else + TU_ATTR_FALLTHROUGH; + #endif + + case CONFIG_FTDI_SET_BAUDRATE: + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + TU_ASSERT_COMPLETE(ftdi_change_speed(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_FLOW_CONTROL)); + break; + #else + TU_ATTR_FALLTHROUGH; + #endif + + case CONFIG_FTDI_FLOW_CONTROL: + // disable flow control + TU_ASSERT_COMPLETE(ftdi_set_request(p_cdc, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0, FTDI_SIO_DISABLE_FLOW_CTRL, ftdi_process_config, CONFIG_FTDI_MODEM_CTRL)); break; case CONFIG_FTDI_MODEM_CTRL: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT_COMPLETE(ftdi_sio_set_modem_ctrl(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_BAUDRATE)); + TU_ASSERT_COMPLETE(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; #endif - case CONFIG_FTDI_SET_BAUDRATE: { - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->requested_line_coding.bit_rate = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM).bit_rate; - TU_ASSERT_COMPLETE(ftdi_sio_set_baudrate(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_DATA)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - } - - case CONFIG_FTDI_SET_DATA: { - #if 0 // TODO set data format - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT_COMPLETE(ftdi_sio_set_data(p_cdc, process_ftdi_config, CONFIG_FTDI_COMPLETE)); - break; - #endif - #endif - - TU_ATTR_FALLTHROUGH; - } - case CONFIG_FTDI_COMPLETE: set_config_complete(idx, 0, true); break; @@ -1173,28 +1279,249 @@ static void ftdi_process_config(tuh_xfer_t* xfer) { //------------- Helper -------------// +static bool ftdi_determine_type(cdch_interface_t * p_cdc, uint8_t const idx) +{ + uint16_t const version = desc_dev[idx]->bcdDevice; + uint8_t const itf_num = p_cdc->bInterfaceNumber; + + p_cdc->ftdi.chip_type = UNKNOWN; + + /* Assume Hi-Speed type */ + p_cdc->ftdi.channel = CHANNEL_A + itf_num; + + switch (version) { + case 0x200: + // FT232A not supported to keep it simple (no extra _read_latency_timer()) + // not testable + // p_cdc->ftdi.chip_type = FT232A; + // p_cdc->ftdi.baud_base = 48000000 / 2; + // p_cdc->ftdi.channel = 0; + // /* + // * FT232B devices have a bug where bcdDevice gets set to 0x200 + // * when iSerialNumber is 0. Assume it is an FT232B in case the + // * latency timer is readable. + // */ + // if (desc->iSerialNumber == 0 && + // _read_latency_timer(port) >= 0) { + // p_cdc->ftdi.chip_type = FT232B; + // } + break; + case 0x400: + p_cdc->ftdi.chip_type = FT232B; + p_cdc->ftdi.channel = 0; + break; + case 0x500: + p_cdc->ftdi.chip_type = FT2232C; + break; + case 0x600: + p_cdc->ftdi.chip_type = FT232R; + p_cdc->ftdi.channel = 0; + break; + case 0x700: + p_cdc->ftdi.chip_type = FT2232H; + break; + case 0x800: + p_cdc->ftdi.chip_type = FT4232H; + break; + case 0x900: + p_cdc->ftdi.chip_type = FT232H; + break; + case 0x1000: + p_cdc->ftdi.chip_type = FTX; + break; + case 0x2800: + p_cdc->ftdi.chip_type = FT2233HP; + break; + case 0x2900: + p_cdc->ftdi.chip_type = FT4233HP; + break; + case 0x3000: + p_cdc->ftdi.chip_type = FT2232HP; + break; + case 0x3100: + p_cdc->ftdi.chip_type = FT4232HP; + break; + case 0x3200: + p_cdc->ftdi.chip_type = FT233HP; + break; + case 0x3300: + p_cdc->ftdi.chip_type = FT232HP; + break; + case 0x3600: + p_cdc->ftdi.chip_type = FT4232HA; + break; + default: + if (version < 0x200) { + p_cdc->ftdi.chip_type = SIO; + p_cdc->ftdi.channel = 0; + } + break; + } + + TU_LOG_P_CDC("%s detected", ftdi_chip_name[p_cdc->ftdi.chip_type]); + + return (p_cdc->ftdi.chip_type != UNKNOWN); +} + +// FT232A not supported +//static uint32_t ftdi_232am_baud_base_to_divisor(uint32_t baud, uint32_t base) +//{ +// uint32_t divisor; +// /* divisor shifted 3 bits to the left */ +// uint32_t divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); +// if ((divisor3 & 0x7) == 7) +// divisor3++; /* round x.7/8 up to x+1 */ +// divisor = divisor3 >> 3; +// divisor3 &= 0x7; +// if (divisor3 == 1) +// divisor |= 0xc000; /* +0.125 */ +// else if (divisor3 >= 4) +// divisor |= 0x4000; /* +0.5 */ +// else if (divisor3 != 0) +// divisor |= 0x8000; /* +0.25 */ +// else if (divisor == 1) +// divisor = 0; /* special case for maximum baud rate */ +// return divisor; +//} + +// FT232A not supported +//static inline uint32_t ftdi_232am_baud_to_divisor(uint32_t baud) +//{ +// return ftdi_232am_baud_base_to_divisor(baud, (uint32_t) 48000000); +//} + static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { - const uint8_t divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; + uint8_t divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; uint32_t divisor; - /* divisor shifted 3 bits to the left */ - uint32_t divisor3 = base / (2 * baud); - divisor = (divisor3 >> 3); - divisor |= (uint32_t) divfrac[divisor3 & 0x7] << 14; - + uint32_t divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); + divisor = divisor3 >> 3; + divisor |= (uint32_t)divfrac[divisor3 & 0x7] << 14; /* Deal with special cases for highest baud rates. */ - if (divisor == 1) { /* 1.0 */ + if (divisor == 1) /* 1.0 */ divisor = 0; - } - else if (divisor == 0x4001) { /* 1.5 */ + else if (divisor == 0x4001) /* 1.5 */ divisor = 1; - } - return divisor; } -static uint32_t ftdi_232bm_baud_to_divisor(cdch_interface_t* p_cdc) { - return ftdi_232bm_baud_base_to_divisor(p_cdc->requested_line_coding.bit_rate, 48000000u); +static inline uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) +{ + return ftdi_232bm_baud_base_to_divisor(baud, 48000000); +} + +static uint32_t ftdi_2232h_baud_base_to_divisor(uint32_t baud, uint32_t base) +{ + static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; + uint32_t divisor; + uint32_t divisor3; + + /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ + divisor3 = DIV_ROUND_CLOSEST(8 * base, 10 * baud); + + divisor = divisor3 >> 3; + divisor |= (uint32_t)divfrac[divisor3 & 0x7] << 14; + /* Deal with special cases for highest baud rates. */ + if (divisor == 1) /* 1.0 */ + divisor = 0; + else if (divisor == 0x4001) /* 1.5 */ + divisor = 1; + /* + * Set this bit to turn off a divide by 2.5 on baud rate generator + * This enables baud rates up to 12Mbaud but cannot reach below 1200 + * baud with this bit set + */ + divisor |= 0x00020000; + return divisor; +} + +static inline uint32_t ftdi_2232h_baud_to_divisor(uint32_t baud) +{ + return ftdi_2232h_baud_base_to_divisor(baud, (uint32_t) 120000000); +} + +static inline uint32_t ftdi_get_divisor(cdch_interface_t * p_cdc) +{ + uint32_t baud = p_cdc->requested_line_coding.bit_rate; + uint32_t div_value = 0; + TU_VERIFY(baud); + + switch (p_cdc->ftdi.chip_type) { + case UNKNOWN: + return 0; + case SIO: + switch (baud) { + case 300: div_value = ftdi_sio_b300; break; + case 600: div_value = ftdi_sio_b600; break; + case 1200: div_value = ftdi_sio_b1200; break; + case 2400: div_value = ftdi_sio_b2400; break; + case 4800: div_value = ftdi_sio_b4800; break; + case 9600: div_value = ftdi_sio_b9600; break; + case 19200: div_value = ftdi_sio_b19200; break; + case 38400: div_value = ftdi_sio_b38400; break; + case 57600: div_value = ftdi_sio_b57600; break; + case 115200: div_value = ftdi_sio_b115200; break; + default: + // Baudrate not supported + return 0; + break; + } + break; + // FT232A not supported + // case FT232A: + // if (baud <= 3000000) { + // div_value = ftdi_232am_baud_to_divisor(baud); + // } else { + // // Baud rate too high! + // baud = 9600; + // div_value = ftdi_232am_baud_to_divisor(9600); + // div_okay = false; + // } + // break; + case FT232B: + case FT2232C: + case FT232R: + case FTX: + TU_VERIFY(baud <= 3000000); // else Baud rate too high! + div_value = ftdi_232bm_baud_to_divisor(baud); + break; + case FT232H: + case FT2232H: + case FT4232H: + case FT4232HA: + case FT232HP: + case FT233HP: + case FT2232HP: + case FT2233HP: + case FT4232HP: + case FT4233HP: + default: + TU_VERIFY(baud <= 12000000); // else Baud rate too high! + if (baud >= 1200) { + div_value = ftdi_2232h_baud_to_divisor(baud); + } else { + div_value = ftdi_232bm_baud_to_divisor(baud); + } + break; + } + + TU_LOG_P_CDC("Baudrate divisor 0x%lu", div_value); + + return div_value; +} + +static uint8_t ftdi_get_idx(tuh_xfer_t * xfer) { + uint8_t const channel = (uint8_t) tu_le16toh(xfer->setup->wIndex); // channel index, or 0 for legacy types + for (uint8_t i = 0; i < CFG_TUH_CDC; i++) { + const cdch_interface_t * p_cdc = &cdch_data[i]; + if (p_cdc->daddr == xfer->daddr && + (!p_cdc->ftdi.channel || // 0 for legacy types (only interface 0) + channel == p_cdc->ftdi.channel)) { // or multi-channel types (interfaces 0..n) + return i; + } + } + + return TUSB_INDEX_INVALID_8; } #endif diff --git a/src/class/cdc/serial/ftdi_sio.h b/src/class/cdc/serial/ftdi_sio.h index 0825f0719..42716f73e 100644 --- a/src/class/cdc/serial/ftdi_sio.h +++ b/src/class/cdc/serial/ftdi_sio.h @@ -25,222 +25,207 @@ #ifndef TUSB_FTDI_SIO_H #define TUSB_FTDI_SIO_H -// VID for matching FTDI devices -#define TU_FTDI_VID 0x0403 +#include // Commands -#define FTDI_SIO_RESET 0 /* Reset the port */ -#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ -#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ -#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ -#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ -#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem status register */ -#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ -#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ -#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */ -#define FTDI_SIO_GET_LATENCY_TIMER 0x0a /* Get the latency timer */ -#define FTDI_SIO_SET_BITMODE 0x0b /* Set bitbang mode */ -#define FTDI_SIO_READ_PINS 0x0c /* Read immediate value of pins */ -#define FTDI_SIO_READ_EEPROM 0x90 /* Read EEPROM */ +#define FTDI_SIO_RESET 0 // Reset the port +#define FTDI_SIO_MODEM_CTRL 1 // Set the modem control register +#define FTDI_SIO_SET_FLOW_CTRL 2 // Set flow control register +#define FTDI_SIO_SET_BAUD_RATE 3 // Set baud rate +#define FTDI_SIO_SET_DATA 4 // Set the data characteristics of the port +#define FTDI_SIO_GET_MODEM_STATUS 5 // Retrieve current value of modem status register +#define FTDI_SIO_SET_EVENT_CHAR 6 // Set the event character +#define FTDI_SIO_SET_ERROR_CHAR 7 // Set the error character +#define FTDI_SIO_SET_LATENCY_TIMER 9 // Set the latency timer +#define FTDI_SIO_GET_LATENCY_TIMER 10 // Get the latency timer +#define FTDI_SIO_SET_BITMODE 11 // Set bitbang mode +#define FTDI_SIO_READ_PINS 12 // Read immediate value of pins +#define FTDI_SIO_READ_EEPROM 0x90 // Read EEPROM -/* FTDI_SIO_RESET */ +// Channel indices for FT2232, FT2232H and FT4232H devices +#define CHANNEL_A 1 +#define CHANNEL_B 2 +#define CHANNEL_C 3 +#define CHANNEL_D 4 + +// Port Identifier Table +#define PIT_DEFAULT 0 // SIOA +#define PIT_SIOA 1 // SIOA +// The device this driver is tested with one has only one port +#define PIT_SIOB 2 // SIOB +#define PIT_PARALLEL 3 // Parallel + +// FTDI_SIO_RESET +#define FTDI_SIO_RESET_REQUEST FTDI_SIO_RESET +#define FTDI_SIO_RESET_REQUEST_TYPE 0x40 #define FTDI_SIO_RESET_SIO 0 #define FTDI_SIO_RESET_PURGE_RX 1 #define FTDI_SIO_RESET_PURGE_TX 2 -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_RESET - * wValue: Control Value - * 0 = Reset SIO - * 1 = Purge RX buffer - * 2 = Purge TX buffer - * wIndex: Port - * wLength: 0 - * Data: None - * - * The Reset SIO command has this effect: - * - * Sets flow control set to 'none' - * Event char = $0D - * Event trigger = disabled - * Purge RX buffer - * Purge TX buffer - * Clear DTR - * Clear RTS - * baud and data format not reset - * - * The Purge RX and TX buffer commands affect nothing except the buffers - * - */ +// FTDI_SIO_SET_BAUDRATE +#define FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_BAUDRATE_REQUEST 3 -/* FTDI_SIO_MODEM_CTRL */ -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_MODEM_CTRL - * wValue: ControlValue (see below) - * wIndex: Port - * wLength: 0 - * Data: None - * - * NOTE: If the device is in RTS/CTS flow control, the RTS set by this - * command will be IGNORED without an error being returned - * Also - you can not set DTR and RTS with one control message - */ +enum ftdi_sio_baudrate { + ftdi_sio_b300 = 0, + ftdi_sio_b600 = 1, + ftdi_sio_b1200 = 2, + ftdi_sio_b2400 = 3, + ftdi_sio_b4800 = 4, + ftdi_sio_b9600 = 5, + ftdi_sio_b19200 = 6, + ftdi_sio_b38400 = 7, + ftdi_sio_b57600 = 8, + ftdi_sio_b115200 = 9 +}; + +// FTDI_SIO_SET_DATA +#define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA +#define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8) +#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8) +#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8) +#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8) +#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8) +#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) +#define FTDI_SIO_SET_BREAK (0x1 << 14) + +// FTDI_SIO_MODEM_CTRL +#define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL #define FTDI_SIO_SET_DTR_MASK 0x1 -#define FTDI_SIO_SET_DTR_HIGH ((FTDI_SIO_SET_DTR_MASK << 8) | 1) -#define FTDI_SIO_SET_DTR_LOW ((FTDI_SIO_SET_DTR_MASK << 8) | 0) +#define FTDI_SIO_SET_DTR_HIGH ((FTDI_SIO_SET_DTR_MASK << 8) | 1) +#define FTDI_SIO_SET_DTR_LOW ((FTDI_SIO_SET_DTR_MASK << 8) | 0) #define FTDI_SIO_SET_RTS_MASK 0x2 #define FTDI_SIO_SET_RTS_HIGH ((FTDI_SIO_SET_RTS_MASK << 8) | 2) #define FTDI_SIO_SET_RTS_LOW ((FTDI_SIO_SET_RTS_MASK << 8) | 0) -/* - * ControlValue - * B0 DTR state - * 0 = reset - * 1 = set - * B1 RTS state - * 0 = reset - * 1 = set - * B2..7 Reserved - * B8 DTR state enable - * 0 = ignore - * 1 = use DTR state - * B9 RTS state enable - * 0 = ignore - * 1 = use RTS state - * B10..15 Reserved - */ - -/* FTDI_SIO_SET_FLOW_CTRL */ +// FTDI_SIO_SET_FLOW_CTRL +#define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL #define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 #define FTDI_SIO_RTS_CTS_HS (0x1 << 8) #define FTDI_SIO_DTR_DSR_HS (0x2 << 8) #define FTDI_SIO_XON_XOFF_HS (0x4 << 8) -/* - * BmRequestType: 0100 0000b - * bRequest: FTDI_SIO_SET_FLOW_CTRL - * wValue: Xoff/Xon - * wIndex: Protocol/Port - hIndex is protocol / lIndex is port - * wLength: 0 - * Data: None - * - * hIndex protocol is: - * B0 Output handshaking using RTS/CTS - * 0 = disabled - * 1 = enabled - * B1 Output handshaking using DTR/DSR - * 0 = disabled - * 1 = enabled - * B2 Xon/Xoff handshaking - * 0 = disabled - * 1 = enabled - * - * A value of zero in the hIndex field disables handshaking - * - * If Xon/Xoff handshaking is specified, the hValue field should contain the - * XOFF character and the lValue field contains the XON character. - */ +// FTDI_SIO_GET_LATENCY_TIMER +#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST FTDI_SIO_GET_LATENCY_TIMER +#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE 0xC0 -/* FTDI_SIO_SET_BAUD_RATE */ -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_SET_BAUDRATE - * wValue: BaudDivisor value - see below - * wIndex: Port - * wLength: 0 - * Data: None - * The BaudDivisor values are calculated as follows (too complicated): - */ +// FTDI_SIO_SET_LATENCY_TIMER +#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER +#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40 -/* FTDI_SIO_SET_DATA */ -#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8) -#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8) -#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8) -#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8) -#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8) -#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) -#define FTDI_SIO_SET_BREAK (0x1 << 14) +// FTDI_SIO_SET_EVENT_CHAR +#define FTDI_SIO_SET_EVENT_CHAR_REQUEST FTDI_SIO_SET_EVENT_CHAR +#define FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40 -/* - * BmRequestType: 0100 0000B - * bRequest: FTDI_SIO_SET_DATA - * wValue: Data characteristics (see below) - * wIndex: Port - * wLength: 0 - * Data: No - * - * Data characteristics - * - * B0..7 Number of data bits - * B8..10 Parity - * 0 = None - * 1 = Odd - * 2 = Even - * 3 = Mark - * 4 = Space - * B11..13 Stop Bits - * 0 = 1 - * 1 = 1.5 - * 2 = 2 - * B14 - * 1 = TX ON (break) - * 0 = TX OFF (normal state) - * B15 Reserved - * - */ +// FTDI_SIO_GET_MODEM_STATUS +#define FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE 0xc0 +#define FTDI_SIO_GET_MODEM_STATUS_REQUEST FTDI_SIO_GET_MODEM_STATUS +#define FTDI_SIO_CTS_MASK 0x10 +#define FTDI_SIO_DSR_MASK 0x20 +#define FTDI_SIO_RI_MASK 0x40 +#define FTDI_SIO_RLSD_MASK 0x80 -/* -* DATA FORMAT -* -* IN Endpoint -* -* The device reserves the first two bytes of data on this endpoint to contain -* the current values of the modem and line status registers. In the absence of -* data, the device generates a message consisting of these two status bytes - * every 40 ms - * - * Byte 0: Modem Status -* -* Offset Description -* B0 Reserved - must be 1 -* B1 Reserved - must be 0 -* B2 Reserved - must be 0 -* B3 Reserved - must be 0 -* B4 Clear to Send (CTS) -* B5 Data Set Ready (DSR) -* B6 Ring Indicator (RI) -* B7 Receive Line Signal Detect (RLSD) -* -* Byte 1: Line Status -* -* Offset Description -* B0 Data Ready (DR) -* B1 Overrun Error (OE) -* B2 Parity Error (PE) -* B3 Framing Error (FE) -* B4 Break Interrupt (BI) -* B5 Transmitter Holding Register (THRE) -* B6 Transmitter Empty (TEMT) -* B7 Error in RCVR FIFO -* -*/ -#define FTDI_RS0_CTS (1 << 4) -#define FTDI_RS0_DSR (1 << 5) -#define FTDI_RS0_RI (1 << 6) -#define FTDI_RS0_RLSD (1 << 7) +// FTDI_SIO_SET_BITMODE +#define FTDI_SIO_SET_BITMODE_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_BITMODE_REQUEST FTDI_SIO_SET_BITMODE -#define FTDI_RS_DR 1 -#define FTDI_RS_OE (1<<1) -#define FTDI_RS_PE (1<<2) -#define FTDI_RS_FE (1<<3) -#define FTDI_RS_BI (1<<4) -#define FTDI_RS_THRE (1<<5) -#define FTDI_RS_TEMT (1<<6) -#define FTDI_RS_FIFO (1<<7) +// Possible bitmodes for FTDI_SIO_SET_BITMODE_REQUEST +#define FTDI_SIO_BITMODE_RESET 0x00 +#define FTDI_SIO_BITMODE_CBUS 0x20 + +// FTDI_SIO_READ_PINS +#define FTDI_SIO_READ_PINS_REQUEST_TYPE 0xc0 +#define FTDI_SIO_READ_PINS_REQUEST FTDI_SIO_READ_PINS + +// FTDI_SIO_READ_EEPROM +#define FTDI_SIO_READ_EEPROM_REQUEST_TYPE 0xc0 +#define FTDI_SIO_READ_EEPROM_REQUEST FTDI_SIO_READ_EEPROM + +#define FTDI_FTX_CBUS_MUX_GPIO 0x8 +#define FTDI_FT232R_CBUS_MUX_GPIO 0xa + +#define FTDI_RS0_CTS (1 << 4) +#define FTDI_RS0_DSR (1 << 5) +#define FTDI_RS0_RI (1 << 6) +#define FTDI_RS0_RLSD (1 << 7) + +#define FTDI_RS_DR 1 +#define FTDI_RS_OE (1<<1) +#define FTDI_RS_PE (1<<2) +#define FTDI_RS_FE (1<<3) +#define FTDI_RS_BI (1<<4) +#define FTDI_RS_THRE (1<<5) +#define FTDI_RS_TEMT (1<<6) +#define FTDI_RS_FIFO (1<<7) + +// chip types and names +enum ftdi_chip_type { + SIO = 0, +// FT232A, + FT232B, + FT2232C, + FT232R, + FT232H, + FT2232H, + FT4232H, + FT4232HA, + FT232HP, + FT233HP, + FT2232HP, + FT2233HP, + FT4232HP, + FT4233HP, + FTX, + UNKNOWN +}; + +#define FTDI_CHIP_NAMES \ + [SIO] = (uint8_t const*) "SIO", /* the serial part of FT8U100AX */ \ +/* [FT232A] = (uint8_t const*) "FT232A", */ \ + [FT232B] = (uint8_t const*) "FT232B", \ + [FT2232C] = (uint8_t const*) "FT2232C/D", \ + [FT232R] = (uint8_t const*) "FT232R", \ + [FT232H] = (uint8_t const*) "FT232H", \ + [FT2232H] = (uint8_t const*) "FT2232H", \ + [FT4232H] = (uint8_t const*) "FT4232H", \ + [FT4232HA] = (uint8_t const*) "FT4232HA", \ + [FT232HP] = (uint8_t const*) "FT232HP", \ + [FT233HP] = (uint8_t const*) "FT233HP", \ + [FT2232HP] = (uint8_t const*) "FT2232HP", \ + [FT2233HP] = (uint8_t const*) "FT2233HP", \ + [FT4232HP] = (uint8_t const*) "FT4232HP", \ + [FT4233HP] = (uint8_t const*) "FT4233HP", \ + [FTX] = (uint8_t const*) "FT-X", \ + [UNKNOWN] = (uint8_t const*) "UNKNOWN" + +// private interface data +typedef struct ftdi_private { + enum ftdi_chip_type chip_type; + uint8_t channel; // channel index, or 0 for legacy types +} ftdi_private_t; + +#define FTDI_OK true +#define FTDI_FAIL false +#define FTDI_NOT_POSSIBLE -1 +#define FTDI_REQUESTED -2 + +// division and round function overtaken from math.h +#define DIV_ROUND_CLOSEST(x, divisor)( \ +{ \ + typeof(x) __x = x; \ + typeof(divisor) __d = divisor; \ + (((typeof(x))-1) > 0 || \ + ((typeof(divisor))-1) > 0 || \ + (((__x) > 0) == ((__d) > 0))) ? \ + (((__x) + ((__d) / 2)) / (__d)) : \ + (((__x) - ((__d) / 2)) / (__d)); \ +} \ +) #endif //TUSB_FTDI_SIO_H diff --git a/src/tusb_option.h b/src/tusb_option.h index 767323bdd..ebf9a4d4d 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -456,9 +456,22 @@ #ifndef CFG_TUH_CDC_FTDI_VID_PID_LIST // List of product IDs that can use the FTDI CDC driver. 0x0403 is FTDI's VID #define CFG_TUH_CDC_FTDI_VID_PID_LIST \ - {0x0403, 0x6001}, {0x0403, 0x6006}, {0x0403, 0x6010}, {0x0403, 0x6011}, \ - {0x0403, 0x6014}, {0x0403, 0x6015}, {0x0403, 0x8372}, {0x0403, 0xFBFA}, \ - {0x0403, 0xCD18} + {0x0403, 0x6001}, /* Similar device to SIO above */ \ + {0x0403, 0x6006}, /* FTDI's alternate PID for above */ \ + {0x0403, 0x6010}, /* Dual channel device */ \ + {0x0403, 0x6011}, /* Quad channel hi-speed device */ \ + {0x0403, 0x6014}, /* Single channel hi-speed device */ \ + {0x0403, 0x6015}, /* FT-X series (FT201X, FT230X, FT231X, etc) */ \ + {0x0403, 0x6040}, /* Dual channel hi-speed device with PD */ \ + {0x0403, 0x6041}, /* Quad channel hi-speed device with PD */ \ + {0x0403, 0x6042}, /* Dual channel hi-speed device with PD */ \ + {0x0403, 0x6043}, /* Quad channel hi-speed device with PD */ \ + {0x0403, 0x6044}, /* Dual channel hi-speed device with PD */ \ + {0x0403, 0x6045}, /* Dual channel hi-speed device with PD */ \ + {0x0403, 0x6048}, /* Quad channel automotive grade hi-speed device */ \ + {0x0403, 0x8372}, /* Product Id SIO application of 8U100AX */ \ + {0x0403, 0xFBFA}, /* Product ID for FT232RL */ \ + {0x0403, 0xCD18}, /* ??? */ #endif #ifndef CFG_TUH_CDC_CP210X From 4547737833de0368354cb4823d908c6b250f92df Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 22 Feb 2024 15:42:33 +0100 Subject: [PATCH 014/382] improved CP210x support --- src/class/cdc/cdc_host.c | 143 +++++++++++++++++++++++----------- src/class/cdc/serial/cp210x.h | 63 ++++++++++++++- src/tusb_option.h | 4 +- 3 files changed, 163 insertions(+), 47 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index f9540efbe..86c010fa7 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -83,7 +83,7 @@ typedef struct { uint8_t requested_line_state; tuh_xfer_cb_t user_control_cb; - #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CH34X + #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X tuh_xfer_cb_t requested_complete_cb; #endif @@ -1533,7 +1533,8 @@ static uint8_t ftdi_get_idx(tuh_xfer_t * xfer) { //------------- Control Request -------------// -static bool cp210x_set_request(cdch_interface_t* p_cdc, uint8_t command, uint16_t value, uint8_t* buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool cp210x_set_request(cdch_interface_t * p_cdc, uint8_t command, uint16_t value, + uint8_t * buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, @@ -1542,12 +1543,12 @@ static bool cp210x_set_request(cdch_interface_t* p_cdc, uint8_t command, uint16_ }, .bRequest = command, .wValue = tu_htole16(value), - .wIndex = p_cdc->bInterfaceNumber, + .wIndex = tu_htole16(p_cdc->bInterfaceNumber), .wLength = tu_htole16(length) }; // use usbh enum buf since application variable does not live long enough - uint8_t* enum_buf = NULL; + uint8_t * enum_buf = NULL; if (buffer && length > 0) { enum_buf = usbh_get_enum_buf(); @@ -1566,18 +1567,52 @@ static bool cp210x_set_request(cdch_interface_t* p_cdc, uint8_t command, uint16_ return tuh_control_xfer(&xfer); } -static bool cp210x_ifc_enable(cdch_interface_t* p_cdc, uint16_t enabled, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static inline bool cp210x_ifc_enable(cdch_interface_t * p_cdc, uint16_t enabled, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return cp210x_set_request(p_cdc, CP210X_IFC_ENABLE, enabled, NULL, 0, complete_cb, user_data); } +static bool cp210x_set_baudrate_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // Check baudrate is supported. It's only a specific list. reference: datasheets and AN205 "CP210x Baud Rate Support" + uint32_t const supported_baudrates_list[] = CP210X_SUPPORTED_BAUDRATES_LIST; + uint8_t i; + for ( i=0; supported_baudrates_list[i]; i++ ){ + if (p_cdc->requested_line_coding.bit_rate == supported_baudrates_list[i]) { + break; + } + } + TU_VERIFY(supported_baudrates_list[i]); + uint32_t baud_le = tu_htole32(p_cdc->requested_line_coding.bit_rate); + + return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, complete_cb, user_data); +} + +static bool cp210x_set_line_ctl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 9, 0); + uint16_t lcr = (uint16_t) ( + ((uint32_t) p_cdc->requested_line_coding.data_bits & 0xf) << 8 | // data bit quantity is stored in bits 8-11 + ((uint32_t) p_cdc->requested_line_coding.parity & 0xf) << 4 | // parity is stored in bits 4-7, same coding + ((uint32_t) p_cdc->requested_line_coding.stop_bits & 0xf)); // parity is stored in bits 0-3, same coding + + return cp210x_set_request(p_cdc, CP210X_SET_LINE_CTL, lcr, NULL, 0, complete_cb, user_data); +} + +static inline bool cp210x_set_mhs(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // CP210x has the same bit coding + return cp210x_set_request(p_cdc, CP210X_SET_MHS, + (uint16_t) ((uint32_t) CP210X_CONTROL_WRITE_DTR | + (uint32_t) CP210X_CONTROL_WRITE_RTS | p_cdc->requested_line_state), + NULL, 0, complete_cb, user_data); +} + //------------- Driver API -------------// // internal control complete to update state such as line state, encoding static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t* p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); TU_LOG_P_CDC("control complete success = %u", success); @@ -1587,6 +1622,12 @@ static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { p_cdc->line_state = p_cdc->requested_line_state; break; + case CP210X_SET_LINE_CTL: + p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; + p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; + p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; + break; + case CP210X_SET_BAUDRATE: p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; break; @@ -1601,46 +1642,55 @@ static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint32_t baud_le = tu_htole32(p_cdc->requested_line_coding.bit_rate); +static bool cp210x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; - return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, - complete_cb ? cp210x_internal_control_complete : NULL, user_data); + TU_ASSERT(cp210x_set_baudrate_request(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); + + return true; } -static bool cp210x_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - (void) p_cdc; - (void) complete_cb; - (void) user_data; - // TODO not implemented yet - return false; -} - -static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - // TODO implement later - (void) p_cdc; - (void) complete_cb; - (void) user_data; - return false; -} - -static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool cp210x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; - return cp210x_set_request(p_cdc, CP210X_SET_MHS, 0x0300 | p_cdc->requested_line_state, NULL, 0, - complete_cb ? cp210x_internal_control_complete : NULL, user_data); + TU_ASSERT(cp210x_set_line_ctl(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); + + return true; +} + +static void cp210x_set_line_coding_stage1_complete(tuh_xfer_t * xfer) { + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + set_line_coding_stage1_complete(xfer, itf_num, + cp210x_set_line_ctl, // control request function to set data format + cp210x_internal_control_complete); // control complete function to be called after request +} + +// 2 stages: set baudrate (stage1) + set data format (stage2) +static bool cp210x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return set_line_coding_sequence(p_cdc, + cp210x_set_baudrate_request, // control request function to set baudrate + cp210x_set_line_ctl, // control request function to set data format + cp210x_set_line_coding_stage1_complete, // function to be called after stage 1 completed + cp210x_internal_control_complete, // control complete function to be called after request + complete_cb, user_data); +} + +static bool cp210x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->user_control_cb = complete_cb; + TU_ASSERT(cp210x_set_mhs(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); + + return true; } //------------- Enumeration -------------// enum { CONFIG_CP210X_IFC_ENABLE = 0, - CONFIG_CP210X_SET_BAUDRATE, + CONFIG_CP210X_SET_BAUDRATE_REQUEST, CONFIG_CP210X_SET_LINE_CTL, CONFIG_CP210X_SET_DTR_RTS, CONFIG_CP210X_COMPLETE }; -static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { +static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // CP210x Interface includes 1 vendor interface + 2 bulk endpoints TU_VERIFY(itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0 && itf_desc->bNumEndpoints == 2); TU_VERIFY(sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) <= max_len); @@ -1657,7 +1707,7 @@ static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui return open_ep_stream_pair(p_cdc, desc_ep); } -static void cp210x_process_config(tuh_xfer_t* xfer) { +static void cp210x_process_config(tuh_xfer_t * xfer) { uintptr_t const state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); @@ -1666,32 +1716,35 @@ static void cp210x_process_config(tuh_xfer_t* xfer) { switch (state) { case CONFIG_CP210X_IFC_ENABLE: - TU_ASSERT_COMPLETE(cp210x_ifc_enable(p_cdc, 1, cp210x_process_config, CONFIG_CP210X_SET_BAUDRATE)); + p_cdc->user_control_cb = cp210x_process_config; // set once for whole process config + TU_ASSERT_COMPLETE(cp210x_ifc_enable(p_cdc, CP210X_UART_ENABLE, cp210x_process_config, + CONFIG_CP210X_SET_BAUDRATE_REQUEST)); break; - case CONFIG_CP210X_SET_BAUDRATE: { + case CONFIG_CP210X_SET_BAUDRATE_REQUEST: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->requested_line_coding.bit_rate = ((cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM).bit_rate; - TU_ASSERT_COMPLETE(cp210x_set_baudrate(p_cdc, cp210x_process_config, CONFIG_CP210X_SET_LINE_CTL)); + p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + TU_ASSERT_COMPLETE(cp210x_set_baudrate_request(p_cdc, cp210x_internal_control_complete, + CONFIG_CP210X_SET_LINE_CTL)); break; #else TU_ATTR_FALLTHROUGH; #endif - } - case CONFIG_CP210X_SET_LINE_CTL: { - #if defined(CFG_TUH_CDC_LINE_CODING_ON_ENUM) && 0 // skip for now - cdc_line_coding_t line_coding = CFG_TUH_CDC_LINE_CODING_ON_ENUM; - break; + case CONFIG_CP210X_SET_LINE_CTL: + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + TU_ASSERT_COMPLETE(cp210x_set_line_ctl(p_cdc, cp210x_internal_control_complete, + CONFIG_CP210X_SET_DTR_RTS)); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif - } case CONFIG_CP210X_SET_DTR_RTS: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT_COMPLETE(cp210x_set_modem_ctrl(p_cdc, cp210x_process_config, CONFIG_CP210X_COMPLETE)); + TU_ASSERT_COMPLETE(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, + CONFIG_CP210X_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; diff --git a/src/class/cdc/serial/cp210x.h b/src/class/cdc/serial/cp210x.h index 2c749f522..e18da7d51 100644 --- a/src/class/cdc/serial/cp210x.h +++ b/src/class/cdc/serial/cp210x.h @@ -28,7 +28,8 @@ // Protocol details can be found at AN571: CP210x Virtual COM Port Interface // https://www.silabs.com/documents/public/application-notes/AN571.pdf -#define TU_CP210X_VID 0x10C4 +// parts are overtaken from vendors driver +// https://www.silabs.com/documents/public/software/cp210x-3.1.0.tar.gz /* Config request codes */ #define CP210X_IFC_ENABLE 0x00 @@ -59,4 +60,64 @@ #define CP210X_SET_BAUDRATE 0x1E #define CP210X_VENDOR_SPECIFIC 0xFF // GPIO, Recipient must be Device +/* SILABSER_IFC_ENABLE_REQUEST_CODE */ +#define CP210X_UART_ENABLE 0x0001 +#define CP210X_UART_DISABLE 0x0000 + +/* SILABSER_SET_BAUDDIV_REQUEST_CODE */ +#define CP210X_BAUD_RATE_GEN_FREQ 0x384000 + +/*SILABSER_SET_LINE_CTL_REQUEST_CODE */ +#define CP210X_BITS_DATA_MASK 0x0f00 +#define CP210X_BITS_DATA_5 0x0500 +#define CP210X_BITS_DATA_6 0x0600 +#define CP210X_BITS_DATA_7 0x0700 +#define CP210X_BITS_DATA_8 0x0800 +#define CP210X_BITS_DATA_9 0x0900 + +#define CP210X_BITS_PARITY_MASK 0x00f0 +#define CP210X_BITS_PARITY_NONE 0x0000 +#define CP210X_BITS_PARITY_ODD 0x0010 +#define CP210X_BITS_PARITY_EVEN 0x0020 +#define CP210X_BITS_PARITY_MARK 0x0030 +#define CP210X_BITS_PARITY_SPACE 0x0040 + +#define CP210X_BITS_STOP_MASK 0x000f +#define CP210X_BITS_STOP_1 0x0000 +#define CP210X_BITS_STOP_1_5 0x0001 +#define CP210X_BITS_STOP_2 0x0002 + +/* SILABSER_SET_BREAK_REQUEST_CODE */ +#define CP210X_BREAK_ON 0x0001 +#define CP210X_BREAK_OFF 0x0000 + +/* SILABSER_SET_MHS_REQUEST_CODE */ +#define CP210X_MCR_DTR 0x0001 +#define CP210X_MCR_RTS 0x0002 +#define CP210X_MCR_ALL 0x0003 +#define CP210X_MSR_CTS 0x0010 +#define CP210X_MSR_DSR 0x0020 +#define CP210X_MSR_RING 0x0040 +#define CP210X_MSR_DCD 0x0080 +#define CP210X_MSR_ALL 0x00F0 + +#define CP210X_CONTROL_WRITE_DTR 0x0100 +#define CP210X_CONTROL_WRITE_RTS 0x0200 + +#define CP210X_LSR_BREAK 0x0001 +#define CP210X_LSR_FRAMING_ERROR 0x0002 +#define CP210X_LSR_HW_OVERRUN 0x0004 +#define CP210X_LSR_QUEUE_OVERRUN 0x0008 +#define CP210X_LSR_PARITY_ERROR 0x0010 +#define CP210X_LSR_ALL 0x001F + +// supported baudrates +// reference: datasheets and AN205 "CP210x Baud Rate Support" +#define CP210X_SUPPORTED_BAUDRATES_LIST { \ + 300, 600, \ + 1200, 1800, 2400, 4000, 4800, 7200, 9600, \ + 14400, 16000, 19200, 28800, 38400, 51200, 56000, 57600, 64000, 76800, \ + 115200, 128000, 153600, 230400, 250000, 256000, 460800, 500000, 576000, 921600, \ + 0 } + #endif //TUSB_CP210X_H diff --git a/src/tusb_option.h b/src/tusb_option.h index ebf9a4d4d..281341685 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -482,7 +482,9 @@ #ifndef CFG_TUH_CDC_CP210X_VID_PID_LIST // List of product IDs that can use the CP210X CDC driver. 0x10C4 is Silicon Labs' VID #define CFG_TUH_CDC_CP210X_VID_PID_LIST \ - {0x10C4, 0xEA60}, {0x10C4, 0xEA70} + { 0x10C4, 0xEA60 }, /* Silicon Labs factory default */ \ + { 0x10C4, 0xEA61 }, /* Silicon Labs factory default */ \ + { 0x10C4, 0xEA70 } /* Silicon Labs Dual Port factory default */ #endif #ifndef CFG_TUH_CDC_CH34X From aabee25e189d2a05cb52e5c54329ab1ec875f084 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 22 Feb 2024 11:45:38 +0100 Subject: [PATCH 015/382] added PL2303 support --- examples/host/cdc_msc_hid/src/tusb_config.h | 1 + .../cdc_msc_hid_freertos/src/tusb_config.h | 1 + src/class/cdc/cdc_host.c | 754 +++++++++++++++++- src/class/cdc/serial/pl2303.h | 172 ++++ src/tusb_option.h | 18 + 5 files changed, 942 insertions(+), 4 deletions(-) create mode 100644 src/class/cdc/serial/pl2303.h diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index e4d74077f..fc956c6d3 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -106,6 +106,7 @@ #define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API +#define CFG_TUH_CDC_PL2303 1 // PL2303 Serial. PL2303 is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index 9dc89dc55..dd732c700 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -111,6 +111,7 @@ #define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API +#define CFG_TUH_CDC_PL2303 1 // PL2303 Serial. PL2303 is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces #define CFG_TUH_MSC 1 #define CFG_TUH_VENDOR 0 diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 86c010fa7..429d0a113 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -38,6 +38,7 @@ #include "serial/ftdi_sio.h" #include "serial/cp210x.h" #include "serial/ch34x.h" +#include "serial/pl2303.h" // Level where CFG_TUSB_DEBUG must be at least for this driver is logged #ifndef CFG_TUH_CDC_LOG_LEVEL @@ -91,6 +92,10 @@ typedef struct { ftdi_private_t ftdi; #endif + #if CFG_TUH_CDC_PL2303 + pl2303_private_t pl2303; + #endif + struct { tu_edpt_stream_t tx; tu_edpt_stream_t rx; @@ -105,7 +110,7 @@ typedef struct { CFG_TUH_MEM_SECTION static cdch_interface_t cdch_data[CFG_TUH_CDC]; -#if CFG_TUH_CDC_FTDI +#if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_PL2303 static tusb_desc_device_t desc_dev[CFG_TUH_CDC][CFG_TUH_ENUMERATION_BUFSIZE]; #endif @@ -164,6 +169,22 @@ static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complet static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif +//------------- PL2303 prototypes -------------// +#if CFG_TUH_CDC_PL2303 +static uint16_t const pl2303_vid_pid_list[][2] = {CFG_TUH_CDC_PL2303_VID_PID_LIST}; +static const struct pl2303_type_data pl2303_type_data[TYPE_COUNT] = {PL2303_TYPE_DATA}; + +CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN + +static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +static void pl2303_process_config(tuh_xfer_t * xfer); + +static bool pl2303_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool pl2303_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool pl2303_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool pl2303_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +#endif + //------------- Common -------------// enum { SERIAL_DRIVER_ACM = 0, @@ -180,6 +201,10 @@ enum { SERIAL_DRIVER_CH34X, #endif +#if CFG_TUH_CDC_PL2303 + SERIAL_DRIVER_PL2303, +#endif + SERIAL_DRIVER_COUNT }; @@ -260,6 +285,22 @@ static const cdch_serial_driver_t serial_drivers[] = { #endif }, #endif + + #if CFG_TUH_CDC_PL2303 + { + .vid_pid_list = pl2303_vid_pid_list, + .vid_pid_count = TU_ARRAY_SIZE(pl2303_vid_pid_list), + .open = pl2303_open, + .process_set_config = pl2303_process_config, + .set_control_line_state = pl2303_set_modem_ctrl, + .set_baudrate = pl2303_set_baudrate, + .set_data_format = pl2303_set_data_format, + .set_line_coding = pl2303_set_line_coding, + #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL + .name = (uint8_t const *) "PL2303" + #endif + } + #endif }; TU_VERIFY_STATIC(TU_ARRAY_SIZE(serial_drivers) == SERIAL_DRIVER_COUNT, "Serial driver count mismatch"); @@ -1863,7 +1904,7 @@ static bool ch34x_modem_ctrl_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t com // internal control complete to update state such as line state, encoding static void ch34x_internal_control_complete(tuh_xfer_t * xfer) { - // CH34x only has 1 interface and wIndex used as payload and not for bInterfaceNumber + // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber uint8_t const itf_num = 0; uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t* p_cdc = get_itf(idx); @@ -1921,7 +1962,8 @@ static bool ch34x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_ } static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t * xfer) { - uint8_t const itf_num = 0; // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber + // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber + uint8_t const itf_num = 0; set_line_coding_stage1_complete(xfer, itf_num, ch34x_write_reg_data_format, // control request function to set data format ch34x_internal_control_complete); // control complete function to be called after request @@ -1981,7 +2023,7 @@ static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uin } static void ch34x_process_config(tuh_xfer_t* xfer) { - // CH34x only has 1 interface and wIndex used as payload and not for bInterfaceNumber + // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber uintptr_t const state = xfer->user_data; uint8_t const itf_num = 0; uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); @@ -2142,4 +2184,708 @@ static uint8_t ch34x_get_lcr(cdch_interface_t * p_cdc) { #endif // CFG_TUH_CDC_CH34X +//--------------------------------------------------------------------+ +// PL2303 +//--------------------------------------------------------------------+ +#if CFG_TUH_CDC_PL2303 + +static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t const idx, uint8_t step, + tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool pl2303_encode_baud_rate(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]); + +//------------- Control Request -------------// + +static bool pl2303_set_request(cdch_interface_t * p_cdc, uint8_t request, uint8_t requesttype, + uint16_t value, uint16_t index, uint8_t * buffer, uint16_t length, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + tusb_control_request_t const request_setup = { + .bmRequestType = requesttype, + .bRequest = request, + .wValue = tu_htole16 (value), + .wIndex = tu_htole16 (index), + .wLength = tu_htole16 (length) + }; + + // use usbh enum buf since application variable does not live long enough + uint8_t * enum_buf = NULL; + + if (buffer && length > 0) { + enum_buf = usbh_get_enum_buf(); + if (request_setup.bmRequestType_bit.direction == TUSB_DIR_OUT) { + tu_memcpy_s(enum_buf, CFG_TUH_ENUMERATION_BUFSIZE, buffer, length); + } + } + + tuh_xfer_t xfer = { + .daddr = p_cdc->daddr, + .ep_addr = 0, + .setup = &request_setup, + .buffer = enum_buf, + .complete_cb = complete_cb, + .user_data = user_data + }; + + return tuh_control_xfer(&xfer); +} + +static bool pl2303_vendor_read(cdch_interface_t * p_cdc, uint16_t value, uint8_t * buf, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) +{ + uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN] ? + PL2303_VENDOR_READ_NREQUEST : PL2303_VENDOR_READ_REQUEST; + + return pl2303_set_request(p_cdc, request, PL2303_VENDOR_READ_REQUEST_TYPE, value, 0, buf, 1, complete_cb, user_data); +} + +static bool pl2303_vendor_write(cdch_interface_t * p_cdc, uint16_t value, uint16_t index, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) +{ + uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN] ? + PL2303_VENDOR_WRITE_NREQUEST : PL2303_VENDOR_WRITE_REQUEST; + + return pl2303_set_request(p_cdc, request, PL2303_VENDOR_WRITE_REQUEST_TYPE, value, index, NULL, 0, complete_cb, user_data); +} + +static inline bool pl2303_supports_hx_status(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) +{ + uint8_t buf; + + return pl2303_set_request(p_cdc, PL2303_VENDOR_READ_REQUEST, PL2303_VENDOR_READ_REQUEST_TYPE, PL2303_READ_TYPE_HX_STATUS, 0, + &buf, 1, complete_cb, user_data); +} + +static inline bool pl2303_set_control_lines(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) +{ + return pl2303_set_request(p_cdc, PL2303_SET_CONTROL_REQUEST, PL2303_SET_CONTROL_REQUEST_TYPE, + p_cdc->requested_line_state, 0, NULL, 0, complete_cb, user_data); +} + +//static bool pl2303_get_line_request(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BUFSIZE]) +//{ +// return pl2303_set_request(p_cdc, PL2303_GET_LINE_REQUEST, PL2303_GET_LINE_REQUEST_TYPE, 0, 0, buf, PL2303_LINE_CODING_BUFSIZE); +//} + +static bool pl2303_set_line_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // the caller has to precheck, that the new line coding different than the current, else false returned + uint8_t buf[PL2303_LINE_CODING_BUFSIZE]; + /* + * Some PL2303 are known to lose bytes if you change serial settings + * even to the same values as before. Thus we actually need to filter + * in this specific case. + */ + // TODO really necessary to check? what to do in this case when no transfer will happen? + // callback is not called... + TU_VERIFY(memcmp(&p_cdc->requested_line_coding, &p_cdc->line_coding, sizeof(cdc_line_coding_t) ) != 0); + + /* For reference buf[6] data bits value */ + TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8, 0); + buf[6] = p_cdc->requested_line_coding.data_bits; + + /* For reference buf[0]:buf[3] baud rate value */ + TU_VERIFY(pl2303_encode_baud_rate(p_cdc, &buf[0])); + + /* For reference buf[4]=0 is 1 stop bits */ + /* For reference buf[4]=1 is 1.5 stop bits */ + /* For reference buf[4]=2 is 2 stop bits */ + buf[4] = p_cdc->requested_line_coding.stop_bits; // PL2303 has the same coding + + /* For reference buf[5]=0 is none parity */ + /* For reference buf[5]=1 is odd parity */ + /* For reference buf[5]=2 is even parity */ + /* For reference buf[5]=3 is mark parity */ + /* For reference buf[5]=4 is space parity */ + buf[5] = p_cdc->requested_line_coding.parity; // PL2303 has the same coding + + return pl2303_set_request(p_cdc, PL2303_SET_LINE_REQUEST, PL2303_SET_LINE_REQUEST_TYPE, 0, 0, + buf, PL2303_LINE_CODING_BUFSIZE, complete_cb, user_data); +} + +//static bool pl2303_set_break(cdch_interface_t * p_cdc, bool enable) +//{ +// uint16_t state = enable ? PL2303_BREAK_ON : PL2303_BREAK_OFF; +// return pl2303_set_request(p_cdc, PL2303_BREAK_REQUEST, PL2303_BREAK_REQUEST_TYPE, state, 0, NULL, 0); +//} + +static inline int pl2303_clear_halt(cdch_interface_t * p_cdc, uint8_t endp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) +{ + /* we don't care if it wasn't halted first. in fact some devices + * (like some ibmcam model 1 units) seem to expect hosts to make + * this request for iso endpoints, which can't halt! + */ + return pl2303_set_request(p_cdc, TUSB_REQ_CLEAR_FEATURE, PL2303_CLEAR_HALT_REQUEST_TYPE, TUSB_REQ_FEATURE_EDPT_HALT, endp, + NULL, 0, complete_cb, user_data); +} + +//------------- Driver API -------------// + +// internal control complete to update state such as line state, encoding +static void pl2303_internal_control_complete(tuh_xfer_t * xfer) { + // PL2303 has only interface 0, because wIndex is used as payload and not for bInterfaceNumber + uint8_t const itf_num = 0; + uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); + bool const success = (xfer->result == XFER_RESULT_SUCCESS); + TU_LOG_P_CDC("control complete success = %u", success); + + if (success) { + if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && + xfer->setup->bmRequestType == PL2303_SET_LINE_REQUEST_TYPE) { + p_cdc->line_coding = p_cdc->requested_line_coding; + } + if (xfer->setup->bRequest == PL2303_SET_CONTROL_REQUEST && + xfer->setup->bmRequestType == PL2303_SET_CONTROL_REQUEST_TYPE) { + p_cdc->line_state = p_cdc->requested_line_state; + } + } + + xfer->complete_cb = p_cdc->user_control_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } +} + +static bool pl2303_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->user_control_cb = complete_cb; + TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); + + return true; +} + +static bool pl2303_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->requested_line_coding.bit_rate = p_cdc->line_coding.bit_rate; + p_cdc->user_control_cb = complete_cb; + TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); + + return true; +} + +static bool pl2303_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + p_cdc->requested_line_coding.stop_bits = p_cdc->line_coding.stop_bits; + p_cdc->requested_line_coding.parity = p_cdc->line_coding.parity; + p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits; + p_cdc->user_control_cb = complete_cb; + TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); + + return true; +} + +static bool pl2303_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // PL2303 has the same bit coding + p_cdc->user_control_cb = complete_cb; + TU_ASSERT(pl2303_set_control_lines(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); + + return true; +} + +//------------- Enumeration -------------// + +enum { + CONFIG_PL2303_GET_DESC = 0, + CONFIG_PL2303_DETECT_TYPE, + CONFIG_PL2303_READ1, + CONFIG_PL2303_WRITE1, + CONFIG_PL2303_READ2, + CONFIG_PL2303_READ3, + CONFIG_PL2303_READ4, + CONFIG_PL2303_WRITE2, + CONFIG_PL2303_READ5, + CONFIG_PL2303_READ6, + CONFIG_PL2303_WRITE3, + CONFIG_PL2303_WRITE4, + CONFIG_PL2303_WRITE5, + CONFIG_PL2303_RESET_ENDP1, + CONFIG_PL2303_RESET_ENDP2, + CONFIG_PL2303_LINE_CODING, + CONFIG_PL2303_MODEM_CONTROL, + CONFIG_PL2303_FLOW_CTRL_READ, + CONFIG_PL2303_FLOW_CTRL_WRITE, + CONFIG_PL2303_COMPLETE +}; + +static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { + // PL2303 Interface includes 1 vendor interface + 1 interrupt endpoints + 2 bulk + TU_VERIFY(itf_desc->bNumEndpoints == 3); + TU_VERIFY(sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t) <= max_len); + + cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); + TU_VERIFY(p_cdc); + + p_cdc->serial_drid = SERIAL_DRIVER_PL2303; + p_cdc->pl2303.serial_private.quirks = 0; + p_cdc->pl2303.supports_hx_status = false; + + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const * ) tu_desc_next(itf_desc); + + // Interrupt endpoint: not used for now + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && + TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); + p_cdc->ep_notif = desc_ep->bEndpointAddress; + desc_ep += 1; + + // data endpoints expected to be in pairs + TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep)); + + return true; +} + +static void pl2303_process_config(tuh_xfer_t * xfer) { + // PL2303 has only interface 0, because wIndex is used as payload and not for bInterfaceNumber + uint8_t const itf_num = 0; + uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); + cdch_interface_t * p_cdc = get_itf(idx); + // state CONFIG_PL2303_READ1 may have no success due to expected stall by pl2303_supports_hx_status() + TU_ASSERT_COMPLETE(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || xfer->user_data == CONFIG_PL2303_READ1)); + uint8_t buf; + int8_t type; + + switch (xfer->user_data) { + + // from here sequence overtaken from Linux Kernel function pl2303_startup() + case CONFIG_PL2303_GET_DESC: + p_cdc->user_control_cb = pl2303_process_config; // set once for whole process config + // get device descriptor + TU_ASSERT_COMPLETE(tuh_descriptor_get_device(xfer->daddr, desc_dev[idx], sizeof(tusb_desc_device_t), + pl2303_process_config, CONFIG_PL2303_DETECT_TYPE)); + break; + + case CONFIG_PL2303_DETECT_TYPE: + // get type and quirks (step 1) + type = pl2303_detect_type (p_cdc, idx, 1, pl2303_process_config, CONFIG_PL2303_READ1); // step 1 + TU_ASSERT_COMPLETE(type!=PL2303_DETECT_TYPE_FAILED); + if (type == PL2303_SUPPORTS_HX_STATUS_TRIGGERED) { + break; + } // else: no transfer triggered and continue with CONFIG_PL2303_READ1 + TU_ATTR_FALLTHROUGH; + + case CONFIG_PL2303_READ1: + // get supports_hx_status, type and quirks (step 2), do special read + p_cdc->pl2303.supports_hx_status = ( // will not be true, if coming directly from previous case + xfer->user_data == CONFIG_PL2303_READ1 && xfer->result == XFER_RESULT_SUCCESS ); + type = pl2303_detect_type (p_cdc, idx, 2, NULL, 0); // step 2 now with supports_hx_status + TU_ASSERT_COMPLETE(type!=PL2303_DETECT_TYPE_FAILED); + p_cdc->pl2303.serial_private.type = &pl2303_type_data[type]; + p_cdc->pl2303.serial_private.quirks |= p_cdc->pl2303.serial_private.type->quirks; + #if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL && 0 // can be activated if necessary + TU_LOG(CFG_TUH_CDC_LOG_LEVEL, "PL2303 bDeviceClass = 0x%02x bMaxPacketSize0 = %u bcdUSB = 0x%04x bcdDevice = 0x%04x", + desc_dev[idx]->bDeviceClass, desc_dev[idx]->bMaxPacketSize0, desc_dev[idx]->bcdUSB, desc_dev[idx]->bcdDevice ); + uint16_t vid, pid; + TU_ASSERT_COMPLETE(tuh_vid_pid_get(p_cdc->daddr, &vid, &pid)); + TU_LOG(CFG_TUH_CDC_LOG_LEVEL, " vid = 0x%04x pid = 0x%04x supports_hx_status = %u type = %s quirks = %u", + vid, pid, p_cdc->pl2303.supports_hx_status, + p_cdc->pl2303.serial_private.type->name, p_cdc->pl2303.serial_private.quirks); + #endif + // purpose unknown, overtaken from Linux Kernel driver + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8484, &buf, pl2303_process_config, CONFIG_PL2303_WRITE1)); + break; + } // else: continue with next step + TU_ATTR_FALLTHROUGH; + + case CONFIG_PL2303_WRITE1: + // purpose unknown, overtaken from Linux Kernel driver + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 0x0404, 0, pl2303_process_config, CONFIG_PL2303_READ2)); + break; + } // else: continue with next step + TU_ATTR_FALLTHROUGH; + + case CONFIG_PL2303_READ2: + // purpose unknown, overtaken from Linux Kernel driver + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8484, &buf, pl2303_process_config, CONFIG_PL2303_READ3)); + break; + } // else: continue with next step + TU_ATTR_FALLTHROUGH; + + case CONFIG_PL2303_READ3: + // purpose unknown, overtaken from Linux Kernel driver + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8383, &buf, pl2303_process_config, CONFIG_PL2303_READ4)); + break; + } // else: continue with next step + TU_ATTR_FALLTHROUGH; + + case CONFIG_PL2303_READ4: + // purpose unknown, overtaken from Linux Kernel driver + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8484, &buf, pl2303_process_config, CONFIG_PL2303_WRITE2)); + break; + } // else: continue with next step + TU_ATTR_FALLTHROUGH; + + case CONFIG_PL2303_WRITE2: + // purpose unknown, overtaken from Linux Kernel driver + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 0x0404, 1, pl2303_process_config, CONFIG_PL2303_READ5)); + break; + } // else: continue with next step + TU_ATTR_FALLTHROUGH; + + case CONFIG_PL2303_READ5: + // purpose unknown, overtaken from Linux Kernel driver + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8484, &buf, pl2303_process_config, CONFIG_PL2303_READ6)); + break; + } // else: continue with next step + TU_ATTR_FALLTHROUGH; + + case CONFIG_PL2303_READ6: + // purpose unknown, overtaken from Linux Kernel driver + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8383, &buf, pl2303_process_config, CONFIG_PL2303_WRITE3)); + break; + } // else: continue with next step + TU_ATTR_FALLTHROUGH; + + case CONFIG_PL2303_WRITE3: + // purpose unknown, overtaken from Linux Kernel driver + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 0, 1, pl2303_process_config, CONFIG_PL2303_WRITE4)); + break; + } // else: continue with next step + TU_ATTR_FALLTHROUGH; + + case CONFIG_PL2303_WRITE4: + // purpose unknown, overtaken from Linux Kernel driver + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 1, 0, pl2303_process_config, CONFIG_PL2303_WRITE5)); + break; + } // else: continue with next step + TU_ATTR_FALLTHROUGH; + + case CONFIG_PL2303_WRITE5: + // purpose unknown, overtaken from Linux Kernel driver + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) { + TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 2, 0x24, pl2303_process_config, CONFIG_PL2303_RESET_ENDP1)); + } else { + TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 2, 0x44, pl2303_process_config, CONFIG_PL2303_RESET_ENDP1)); + } + break; + } // else: continue with next step + TU_ATTR_FALLTHROUGH; + + // from here sequence overtaken from Linux Kernel function pl2303_open() + case CONFIG_PL2303_RESET_ENDP1: + // step 1 + if (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) { + TU_ASSERT_COMPLETE(pl2303_clear_halt(p_cdc, PL2303_OUT_EP, pl2303_process_config, CONFIG_PL2303_RESET_ENDP2)); + } else { + /* reset upstream data pipes */ + if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, PL2303_HXN_RESET_REG, // skip CONFIG_PL2303_RESET_ENDP2, no 2nd step + PL2303_HXN_RESET_UPSTREAM_PIPE | PL2303_HXN_RESET_DOWNSTREAM_PIPE, + pl2303_process_config, CONFIG_PL2303_LINE_CODING)); + } else { + pl2303_vendor_write(p_cdc, 8, 0, pl2303_process_config, CONFIG_PL2303_RESET_ENDP2); + } + } + break; + + case CONFIG_PL2303_RESET_ENDP2: + // step 2 + if (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) { + TU_ASSERT_COMPLETE(pl2303_clear_halt(p_cdc, PL2303_IN_EP, pl2303_process_config, CONFIG_PL2303_LINE_CODING)); + } else { + /* reset upstream data pipes */ + if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { + // here nothing to do, only structure of previous step overtaken for better reading and comparison + } else { + TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 9, 0, pl2303_process_config, CONFIG_PL2303_LINE_CODING)); + } + } + break; + + // from here sequence overtaken from Linux Kernel function pl2303_set_termios() + // unnecessary pl2303_get_line_request() is skipped due to a stall + case CONFIG_PL2303_LINE_CODING: + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + TU_ASSERT_COMPLETE( pl2303_set_line_request(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_MODEM_CONTROL)); + break; + #else + TU_ATTR_FALLTHROUGH; + #endif + + case CONFIG_PL2303_MODEM_CONTROL: + #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + TU_ASSERT_COMPLETE(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_FLOW_CTRL_READ)); + break; + #else + TU_ATTR_FALLTHROUGH; + #endif + + case CONFIG_PL2303_FLOW_CTRL_READ: + // read flow control register for modify & write back in next step + if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { + TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, PL2303_HXN_FLOWCTRL_REG, &buf, pl2303_process_config, + CONFIG_PL2303_FLOW_CTRL_WRITE)); + } else { + TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0, &buf, pl2303_process_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); + } + break; + + case CONFIG_PL2303_FLOW_CTRL_WRITE: + // no flow control + buf = xfer->buffer[0]; + if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { + buf &= (uint8_t) ~PL2303_HXN_FLOWCTRL_MASK; + buf |= PL2303_HXN_FLOWCTRL_NONE; + TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, PL2303_HXN_FLOWCTRL_REG, buf, pl2303_process_config, + CONFIG_PL2303_COMPLETE)); + } else { + buf &= (uint8_t) ~PL2303_FLOWCTRL_MASK; + TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 0, buf, pl2303_process_config, CONFIG_PL2303_COMPLETE)); + } + break; + + case CONFIG_PL2303_COMPLETE: + set_config_complete(idx, 0, true); + break; + + default: + set_config_complete(idx, 0, false); + break; + } +} + +//------------- Helper -------------// + +static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t const idx, uint8_t step, + tuh_xfer_cb_t complete_cb, uintptr_t user_data ) +{ + /* + * Legacy PL2303H, variants 0 and 1 (difference unknown). + */ + if (desc_dev[idx]->bDeviceClass == 0x02) { + return TYPE_H; /* variant 0 */ + } + + if (desc_dev[idx]->bMaxPacketSize0 != 0x40) { + if (desc_dev[idx]->bDeviceClass == 0x00 || desc_dev[idx]->bDeviceClass == 0xff) { + return TYPE_H; /* variant 1 */ + } + return TYPE_H; /* variant 0 */ + } + + switch (desc_dev[idx]->bcdUSB) { + case 0x101: + /* USB 1.0.1? Let's assume they meant 1.1... */ + TU_ATTR_FALLTHROUGH; + case 0x110: + switch (desc_dev[idx]->bcdDevice) { + case 0x300: + return TYPE_HX; + case 0x400: + return TYPE_HXD; + default: + return TYPE_HX; + } + break; + case 0x200: + switch (desc_dev[idx]->bcdDevice) { + case 0x100: /* GC */ + case 0x105: + return TYPE_HXN; + case 0x300: /* GT / TA */ + if (step == 1) { + // step 1 trigger pl2303_supports_hx_status() request + TU_ASSERT(pl2303_supports_hx_status (p_cdc, complete_cb, user_data), PL2303_DETECT_TYPE_FAILED); + return PL2303_SUPPORTS_HX_STATUS_TRIGGERED; + } else { + // step 2 use supports_hx_status + if (p_cdc->pl2303.supports_hx_status) { + return TYPE_TA; + } + } + TU_ATTR_FALLTHROUGH; + case 0x305: + case 0x400: /* GL */ + case 0x405: + return TYPE_HXN; + case 0x500: /* GE / TB */ + if (step == 1) { + // step 1 trigger pl2303_supports_hx_status() request + TU_ASSERT(pl2303_supports_hx_status (p_cdc, complete_cb, user_data), PL2303_DETECT_TYPE_FAILED); + return PL2303_SUPPORTS_HX_STATUS_TRIGGERED; + } else { + // step 2 use supports_hx_status + if (p_cdc->pl2303.supports_hx_status) { + return TYPE_TB; + } + } + TU_ATTR_FALLTHROUGH; + case 0x505: + case 0x600: /* GS */ + case 0x605: + case 0x700: /* GR */ + case 0x705: + return TYPE_HXN; + default: + break; + } + break; + default: break; + } + + TU_LOG_P_CDC("unknown device type bcdUSB = 0x%04x", desc_dev[idx]->bcdUSB); + + return PL2303_DETECT_TYPE_FAILED; +} + +/* + * Returns the nearest supported baud rate that can be set directly without + * using divisors. + */ +static uint32_t pl2303_get_supported_baud_rate(uint32_t baud) +{ + static const uint32_t baud_sup[] = { + 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, + 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800, + 614400, 921600, 1228800, 2457600, 3000000, 6000000 + }; + + uint8_t i; + for (i = 0; i < TU_ARRAY_SIZE(baud_sup); ++i) { + if (baud_sup[i] > baud) { + break; + } + } + + if (i == TU_ARRAY_SIZE(baud_sup)) { + baud = baud_sup[i - 1]; + } else if (i > 0 && (baud_sup[i] - baud) > (baud - baud_sup[i - 1])) { + baud = baud_sup[i - 1]; + } else { + baud = baud_sup[i]; + } + + return baud; +} + +/* + * NOTE: If unsupported baud rates are set directly, the PL2303 seems to + * use 9600 baud. + */ +static uint32_t pl2303_encode_baud_rate_direct(uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE], uint32_t baud) +{ + uint32_t baud_le = tu_htole32(baud); + buf[0] = (uint8_t) ( baud_le & 0xff); + buf[1] = (uint8_t) ((baud_le >> 8) & 0xff); + buf[2] = (uint8_t) ((baud_le >> 16) & 0xff); + buf[3] = (uint8_t) ((baud_le >> 24) & 0xff); + + return baud; +} + +static uint32_t pl2303_encode_baud_rate_divisor(uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE], uint32_t baud) +{ + uint32_t baseline, mantissa, exponent; + + /* + * Apparently the formula is: + * baudrate = 12M * 32 / (mantissa * 4^exponent) + * where + * mantissa = buf[8:0] + * exponent = buf[11:9] + */ + baseline = 12000000 * 32; + mantissa = baseline / baud; + if (mantissa == 0) + mantissa = 1; /* Avoid dividing by zero if baud > 32 * 12M. */ + exponent = 0; + while (mantissa >= 512) { + if (exponent < 7) { + mantissa >>= 2; /* divide by 4 */ + exponent++; + } else { + /* Exponent is maxed. Trim mantissa and leave. */ + mantissa = 511; + break; + } + } + + buf[3] = 0x80; + buf[2] = 0; + buf[1] = (uint8_t) ((exponent << 1 | mantissa >> 8) & 0xff); + buf[0] = (uint8_t) (mantissa & 0xff); + + /* Calculate and return the exact baud rate. */ + baud = (baseline / mantissa) >> (exponent << 1); + + return baud; +} + +static uint32_t pl2303_encode_baud_rate_divisor_alt(uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE], uint32_t baud) +{ + uint32_t baseline, mantissa, exponent; + + /* + * Apparently, for the TA version the formula is: + * baudrate = 12M * 32 / (mantissa * 2^exponent) + * where + * mantissa = buf[10:0] + * exponent = buf[15:13 16] + */ + baseline = 12000000 * 32; + mantissa = baseline / baud; + if (mantissa == 0) { + mantissa = 1; /* Avoid dividing by zero if baud > 32 * 12M. */ + } + exponent = 0; + while (mantissa >= 2048) { + if (exponent < 15) { + mantissa >>= 1; /* divide by 2 */ + exponent++; + } else { + /* Exponent is maxed. Trim mantissa and leave. */ + mantissa = 2047; + break; + } + } + + buf[3] = 0x80; + buf[2] = (uint8_t) (exponent & 0x01); + buf[1] = (uint8_t) (((exponent & (uint32_t) ~0x01) << 4 | mantissa >> 8 ) & 0xff); + buf[0] = (uint8_t) (mantissa & 0xff); + + /* Calculate and return the exact baud rate. */ + baud = (baseline / mantissa) >> exponent; + + return baud; +} + +static bool pl2303_encode_baud_rate(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]) +{ + uint32_t baud = p_cdc->requested_line_coding.bit_rate; + uint32_t baud_sup; + + TU_VERIFY(baud && baud <= p_cdc->pl2303.serial_private.type->max_baud_rate); + /* + * Use direct method for supported baud rates, otherwise use divisors. + * Newer chip types do not support divisor encoding. + */ + if (p_cdc->pl2303.serial_private.type->no_divisors) { + baud_sup = baud; + } else { + baud_sup = pl2303_get_supported_baud_rate(baud); + } + + if (baud == baud_sup) { + baud = pl2303_encode_baud_rate_direct(buf, baud); + } else if (p_cdc->pl2303.serial_private.type->alt_divisors) { + baud = pl2303_encode_baud_rate_divisor_alt(buf, baud); + } else { + baud = pl2303_encode_baud_rate_divisor(buf, baud); + } + TU_LOG_P_CDC("real baudrate = %lu", baud); + + return true; +} + +#endif // CFG_TUH_CDC_PL2303 + #endif diff --git a/src/class/cdc/serial/pl2303.h b/src/class/cdc/serial/pl2303.h new file mode 100644 index 000000000..bf264191b --- /dev/null +++ b/src/class/cdc/serial/pl2303.h @@ -0,0 +1,172 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 Heiko Kuester + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _PL2303_H_ +#define _PL2303_H_ + +#include +#include + +// There is no official documentation for the PL2303 chips. +// Reference can be found +// - https://github.com/torvalds/linux/blob/master/drivers/usb/serial/pl2303.h and +// https://github.com/torvalds/linux/blob/master/drivers/usb/serial/pl2303.c +// - https://github.com/freebsd/freebsd-src/blob/main/sys/dev/usb/serial/uplcom.c + +/* quirks */ +#define PL2303_QUIRK_UART_STATE_IDX0 1 +#define PL2303_QUIRK_LEGACY 2 +#define PL2303_QUIRK_ENDPOINT_HACK 4 + +/* requests and bits */ +#define PL2303_SET_LINE_REQUEST_TYPE 0x21 // class request host to device interface +#define PL2303_SET_LINE_REQUEST 0x20 // dec 32 + +#define PL2303_SET_CONTROL_REQUEST_TYPE 0x21 // class request host to device interface +#define PL2303_SET_CONTROL_REQUEST 0x22 // dec 34 +#define PL2303_CONTROL_DTR 0x01 // dec 1 +#define PL2303_CONTROL_RTS 0x02 // dec 2 + +#define PL2303_BREAK_REQUEST_TYPE 0x21 // class request host to device interface +#define PL2303_BREAK_REQUEST 0x23 // dec 35 +#define PL2303_BREAK_ON 0xffff +#define PL2303_BREAK_OFF 0x0000 + +#define PL2303_GET_LINE_REQUEST_TYPE 0xa1 // class request device to host interface +#define PL2303_GET_LINE_REQUEST 0x21 // dec 33 + +#define PL2303_VENDOR_WRITE_REQUEST_TYPE 0x40 // vendor request host to device interface +#define PL2303_VENDOR_WRITE_REQUEST 0x01 // dec 1 +#define PL2303_VENDOR_WRITE_NREQUEST 0x80 // dec 128 + +#define PL2303_VENDOR_READ_REQUEST_TYPE 0xc0 // vendor request device to host interface +#define PL2303_VENDOR_READ_REQUEST 0x01 // dec 1 +#define PL2303_VENDOR_READ_NREQUEST 0x81 // dec 129 + +#define PL2303_UART_STATE_INDEX 8 +#define PL2303_UART_STATE_MSR_MASK 0x8b +#define PL2303_UART_STATE_TRANSIENT_MASK 0x74 +#define PL2303_UART_DCD 0x01 +#define PL2303_UART_DSR 0x02 +#define PL2303_UART_BREAK_ERROR 0x04 +#define PL2303_UART_RING 0x08 +#define PL2303_UART_FRAME_ERROR 0x10 +#define PL2303_UART_PARITY_ERROR 0x20 +#define PL2303_UART_OVERRUN_ERROR 0x40 +#define PL2303_UART_CTS 0x80 + +#define PL2303_FLOWCTRL_MASK 0xf0 + +#define PL2303_CLEAR_HALT_REQUEST_TYPE 0x02 // standard request host to device endpoint + +/* registers via vendor read/write requests */ +#define PL2303_READ_TYPE_HX_STATUS 0x8080 + +#define PL2303_HXN_RESET_REG 0x07 +#define PL2303_HXN_RESET_UPSTREAM_PIPE 0x02 +#define PL2303_HXN_RESET_DOWNSTREAM_PIPE 0x01 + +#define PL2303_HXN_FLOWCTRL_REG 0x0a +#define PL2303_HXN_FLOWCTRL_MASK 0x1c +#define PL2303_HXN_FLOWCTRL_NONE 0x1c +#define PL2303_HXN_FLOWCTRL_RTS_CTS 0x18 +#define PL2303_HXN_FLOWCTRL_XON_XOFF 0x0c + +/* type data */ +enum pl2303_type { + TYPE_H, + TYPE_HX, + TYPE_TA, + TYPE_TB, + TYPE_HXD, + TYPE_HXN, + TYPE_COUNT +}; + +struct pl2303_type_data { + uint8_t const *name; + uint32_t const max_baud_rate; + uint8_t const quirks; + uint16_t const no_autoxonxoff:1; + uint16_t const no_divisors:1; + uint16_t const alt_divisors:1; +}; + +#define PL2303_TYPE_DATA \ + [TYPE_H] = { \ + .name = (uint8_t const*)"H", \ + .max_baud_rate = 1228800, \ + .quirks = PL2303_QUIRK_LEGACY, \ + .no_autoxonxoff = true, \ + }, \ + [TYPE_HX] = { \ + .name = (uint8_t const*)"HX", \ + .max_baud_rate = 6000000, \ + }, \ + [TYPE_TA] = { \ + .name = (uint8_t const*)"TA", \ + .max_baud_rate = 6000000, \ + .alt_divisors = true, \ + }, \ + [TYPE_TB] = { \ + .name = (uint8_t const*)"TB", \ + .max_baud_rate = 12000000, \ + .alt_divisors = true, \ + }, \ + [TYPE_HXD] = { \ + .name = (uint8_t const*)"HXD", \ + .max_baud_rate = 12000000, \ + }, \ + [TYPE_HXN] = { \ + .name = (uint8_t const*)"G (HXN)", \ + .max_baud_rate = 12000000, \ + .no_divisors = true, \ + } + +/* private data types */ +struct pl2303_serial_private { + const struct pl2303_type_data* type; + uint8_t quirks; +}; + +typedef struct TU_ATTR_PACKED { + struct pl2303_serial_private serial_private; + bool supports_hx_status; +} pl2303_private_t; + +/* buffer sizes for line coding data */ +#define PL2303_LINE_CODING_BUFSIZE 7 +#define PL2303_LINE_CODING_BAUDRATE_BUFSIZE 4 + +/* bulk endpoints */ +#define PL2303_OUT_EP 0x02 +#define PL2303_IN_EP 0x83 + +/* return values of pl2303_detect_type() */ +#define PL2303_SUPPORTS_HX_STATUS_TRIGGERED -1 +#define PL2303_DETECT_TYPE_FAILED -2 + +#endif /* _PL2303_H_ */ diff --git a/src/tusb_option.h b/src/tusb_option.h index 281341685..f023b490a 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -504,6 +504,24 @@ { 0x9986, 0x7523 } /* overtaken from Linux Kernel driver /drivers/usb/serial/ch341.c */ #endif +#ifndef CFG_TUH_CDC_PL2303 + // PL2303 is not part of CDC class, only to re-use CDC driver API + #define CFG_TUH_CDC_PL2303 0 +#endif + +#ifndef CFG_TUH_CDC_PL2303_VID_PID_QUIRKS_LIST + // List of product IDs that can use the PL2303 CDC driver + #define CFG_TUH_CDC_PL2303_VID_PID_LIST \ + { 0x067b, 0x2303 }, /* initial 2303 */ \ + { 0x067b, 0x2304 }, /* TB */ \ + { 0x067b, 0x23a3 }, /* GC */ \ + { 0x067b, 0x23b3 }, /* GB */ \ + { 0x067b, 0x23c3 }, /* GT */ \ + { 0x067b, 0x23d3 }, /* GL */ \ + { 0x067b, 0x23e3 }, /* GE */ \ + { 0x067b, 0x23f3 } /* GS */ +#endif + #ifndef CFG_TUH_HID #define CFG_TUH_HID 0 #endif From ea175a78aad5bd258954aa61550aae0162bc884b Mon Sep 17 00:00:00 2001 From: IngHK Date: Sat, 24 Feb 2024 13:00:46 +0100 Subject: [PATCH 016/382] updated contribution, readme and some comments --- CONTRIBUTORS.rst | 7 +++++++ README.rst | 2 +- src/class/cdc/cdc_host.c | 6 +++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index 085f8082a..451ac0783 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -31,6 +31,13 @@ Notable contributors - Most features development +`Heiko Kuester `__ +-------------------------------------------- + +- Add CH34x and PL2303 support (CDC host) +- Improve FTDI and CP210x support (CDC host) + + `Hristo Gochkov `__ ------------------------------------------------- diff --git a/README.rst b/README.rst index fe2417451..6922c231e 100644 --- a/README.rst +++ b/README.rst @@ -77,7 +77,7 @@ Host Stack - Human Interface Device (HID): Keyboard, Mouse, Generic - Mass Storage Class (MSC) - Communication Device Class: CDC-ACM -- Vendor serial over USB: FTDI, CP210x +- Vendor serial over USB: FTDI, CP210x, CH34x, PL2303 - Hub with multiple-level support Similar to the Device Stack, if you have a special requirement, `usbh_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 429d0a113..b35a8fd93 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -24,7 +24,7 @@ * This file is part of the TinyUSB stack. * * Contribution - * - Heiko Kuester: CH34x support + * - Heiko Kuester: add support of CH34x & PL2303, improve support of FTDI & CP210x */ #include "tusb_option.h" @@ -818,12 +818,12 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); TU_LOG_P_CDC("set config"); - // fake transfer to kick-off process + // fake transfer to kick-off process_set_config() tuh_xfer_t xfer; xfer.daddr = daddr; xfer.result = XFER_RESULT_SUCCESS; xfer.setup = &request; - xfer.user_data = 0; // initial state + xfer.user_data = 0; // initial state 0 serial_drivers[p_cdc->serial_drid].process_set_config(&xfer); return true; From 2b507dba4d9901d1208c4166bbc6026bb6062c9b Mon Sep 17 00:00:00 2001 From: IngHK Date: Sat, 24 Feb 2024 13:01:38 +0100 Subject: [PATCH 017/382] small changes & code style --- src/class/cdc/cdc_host.c | 236 ++++++++++++++++++++------------------- 1 file changed, 124 insertions(+), 112 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index b35a8fd93..50aa4b6f0 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -85,7 +85,7 @@ typedef struct { tuh_xfer_cb_t user_control_cb; #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X - tuh_xfer_cb_t requested_complete_cb; + tuh_xfer_cb_t requested_complete_cb; #endif #if CFG_TUH_CDC_FTDI @@ -119,54 +119,54 @@ static cdch_interface_t cdch_data[CFG_TUH_CDC]; //--------------------------------------------------------------------+ //------------- ACM prototypes -------------// -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -static void acm_process_config(tuh_xfer_t* xfer); +static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +static void acm_process_config(tuh_xfer_t * xfer); -static bool acm_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_control_line_state(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_control_line_state(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); //------------- FTDI prototypes -------------// #if CFG_TUH_CDC_FTDI static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST}; #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL -static uint8_t const * ftdi_chip_name[] = { FTDI_CHIP_NAMES }; + static uint8_t const * ftdi_chip_name[] = { FTDI_CHIP_NAMES }; #endif -static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); -static void ftdi_process_config(tuh_xfer_t* xfer); +static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); +static void ftdi_process_config(tuh_xfer_t * xfer); -static bool ftdi_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif //------------- CP210X prototypes -------------// #if CFG_TUH_CDC_CP210X static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIST}; -static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -static void cp210x_process_config(tuh_xfer_t* xfer); +static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +static void cp210x_process_config(tuh_xfer_t * xfer); -static bool cp210x_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif //------------- CH34x prototypes -------------// #if CFG_TUH_CDC_CH34X static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST}; -static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len); -static void ch34x_process_config(tuh_xfer_t* xfer); +static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); +static void ch34x_process_config(tuh_xfer_t * xfer); -static bool ch34x_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ch34x_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ch34x_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ch34x_set_modem_ctrl(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif //------------- PL2303 prototypes -------------// @@ -211,14 +211,14 @@ enum { typedef struct { uint16_t const (*vid_pid_list)[2]; uint16_t const vid_pid_count; - bool (*const open)(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); - void (*const process_set_config)(tuh_xfer_t* xfer); - bool (*const set_control_line_state)(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_baudrate)(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_data_format)(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_line_coding)(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const open)(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); + void (*const process_set_config)(tuh_xfer_t * xfer); + bool (*const set_control_line_state)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_baudrate)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_data_format)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + bool (*const set_line_coding)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - uint8_t const * name; + uint8_t const * name; #endif } cdch_serial_driver_t; @@ -309,17 +309,17 @@ TU_VERIFY_STATIC(TU_ARRAY_SIZE(serial_drivers) == SERIAL_DRIVER_COUNT, "Serial d // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -static inline cdch_interface_t* get_itf(uint8_t idx) { +static inline cdch_interface_t * get_itf(uint8_t idx) { TU_ASSERT(idx < CFG_TUH_CDC, NULL); - cdch_interface_t* p_cdc = &cdch_data[idx]; + cdch_interface_t * p_cdc = &cdch_data[idx]; return (p_cdc->daddr != 0) ? p_cdc : NULL; } static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) { for(uint8_t i=0; idaddr == daddr) && + cdch_interface_t * p_cdc = &cdch_data[i]; + if ((p_cdc->daddr == daddr) && (ep_addr == p_cdc->ep_notif || ep_addr == p_cdc->stream.rx.ep_addr || ep_addr == p_cdc->stream.tx.ep_addr)) { return i; } @@ -328,10 +328,10 @@ static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) { return TUSB_INDEX_INVALID_8; } -static cdch_interface_t* make_new_itf(uint8_t daddr, tusb_desc_interface_t const *itf_desc) { +static cdch_interface_t * make_new_itf(uint8_t daddr, tusb_desc_interface_t const * itf_desc) { for(uint8_t i=0; idaddr = daddr; p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber; p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass; @@ -345,7 +345,7 @@ static cdch_interface_t* make_new_itf(uint8_t daddr, tusb_desc_interface_t const return NULL; } -static bool open_ep_stream_pair(cdch_interface_t* p_cdc , tusb_desc_endpoint_t const *desc_ep); +static bool open_ep_stream_pair(cdch_interface_t * p_cdc , tusb_desc_endpoint_t const *desc_ep); //--------------------------------------------------------------------+ // APPLICATION API @@ -353,21 +353,21 @@ static bool open_ep_stream_pair(cdch_interface_t* p_cdc , tusb_desc_endpoint_t c uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num) { for (uint8_t i = 0; i < CFG_TUH_CDC; i++) { - const cdch_interface_t* p_cdc = &cdch_data[i]; + const cdch_interface_t * p_cdc = &cdch_data[i]; if (p_cdc->daddr == daddr && p_cdc->bInterfaceNumber == itf_num) return i; } return TUSB_INDEX_INVALID_8; } -bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { - cdch_interface_t* p_cdc = get_itf(idx); +bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t * info) { + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && info); info->daddr = p_cdc->daddr; // re-construct descriptor - tusb_desc_interface_t* desc = &info->desc; + tusb_desc_interface_t * desc = &info->desc; desc->bLength = sizeof(tusb_desc_interface_t); desc->bDescriptorType = TUSB_DESC_INTERFACE; @@ -383,27 +383,27 @@ bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { } bool tuh_cdc_mounted(uint8_t idx) { - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return p_cdc->mounted; } bool tuh_cdc_get_dtr(uint8_t idx) { - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_DTR) ? true : false; } bool tuh_cdc_get_rts(uint8_t idx) { - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_RTS) ? true : false; } -bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding) { - cdch_interface_t* p_cdc = get_itf(idx); +bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t * line_coding) { + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); *line_coding = p_cdc->line_coding; @@ -415,29 +415,29 @@ bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding) // Write //--------------------------------------------------------------------+ -uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize) { - cdch_interface_t* p_cdc = get_itf(idx); +uint32_t tuh_cdc_write(uint8_t idx, void const * buffer, uint32_t bufsize) { + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_write(&p_cdc->stream.tx, buffer, bufsize); } uint32_t tuh_cdc_write_flush(uint8_t idx) { - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_write_xfer(&p_cdc->stream.tx); } bool tuh_cdc_write_clear(uint8_t idx) { - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_clear(&p_cdc->stream.tx); } uint32_t tuh_cdc_write_available(uint8_t idx) { - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_write_available(&p_cdc->stream.tx); @@ -447,33 +447,34 @@ uint32_t tuh_cdc_write_available(uint8_t idx) { // Read //--------------------------------------------------------------------+ -uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize) { - cdch_interface_t* p_cdc = get_itf(idx); +uint32_t tuh_cdc_read (uint8_t idx, void * buffer, uint32_t bufsize) { + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_read(&p_cdc->stream.rx, buffer, bufsize); } uint32_t tuh_cdc_read_available(uint8_t idx) { - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_read_available(&p_cdc->stream.rx); } -bool tuh_cdc_peek(uint8_t idx, uint8_t* ch) { - cdch_interface_t* p_cdc = get_itf(idx); +bool tuh_cdc_peek(uint8_t idx, uint8_t * ch) { + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); return tu_edpt_stream_peek(&p_cdc->stream.rx, ch); } bool tuh_cdc_read_clear (uint8_t idx) { - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); bool ret = tu_edpt_stream_clear(&p_cdc->stream.rx); tu_edpt_stream_read_xfer(&p_cdc->stream.rx); + return ret; } @@ -657,7 +658,7 @@ void cdch_init(void) { tu_memclr(cdch_data, sizeof(cdch_data)); for (size_t i = 0; i < CFG_TUH_CDC; i++) { - cdch_interface_t* p_cdc = &cdch_data[i]; + cdch_interface_t * p_cdc = &cdch_data[i]; tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, @@ -671,7 +672,7 @@ void cdch_init(void) { void cdch_close(uint8_t daddr) { for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { - cdch_interface_t* p_cdc = &cdch_data[idx]; + cdch_interface_t * p_cdc = &cdch_data[idx]; if (p_cdc->daddr == daddr) { TU_LOG_P_CDC("close"); @@ -695,35 +696,37 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc); - if ( ep_addr == p_cdc->stream.tx.ep_addr ) { + if (ep_addr == p_cdc->stream.tx.ep_addr) { // invoke tx complete callback to possibly refill tx fifo if (tuh_cdc_tx_complete_cb) tuh_cdc_tx_complete_cb(idx); - if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) ) { + if (0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx)) { // If there is no data left, a ZLP should be sent if: // - xferred_bytes is multiple of EP Packet size and not zero tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes); } - } else if ( ep_addr == p_cdc->stream.rx.ep_addr ) { + } else if (ep_addr == p_cdc->stream.rx.ep_addr) { #if CFG_TUH_CDC_FTDI if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI) { // FTDI reserve 2 bytes for status // uint8_t status[2] = {p_cdc->stream.rx.ep_buf[0], p_cdc->stream.rx.ep_buf[1]}; tu_edpt_stream_read_xfer_complete_offset(&p_cdc->stream.rx, xferred_bytes, 2); - }else + } else #endif { tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); } // invoke receive callback - if (tuh_cdc_rx_cb) tuh_cdc_rx_cb(idx); + if (tuh_cdc_rx_cb) { + tuh_cdc_rx_cb(idx); + } // prepare for next transfer if needed tu_edpt_stream_read_xfer(&p_cdc->stream.rx); - }else if ( ep_addr == p_cdc->ep_notif ) { + } else if (ep_addr == p_cdc->ep_notif) { // TODO handle notification endpoint - }else { + } else { TU_ASSERT(false); } @@ -734,7 +737,7 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t // Enumeration //--------------------------------------------------------------------+ -static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t const* desc_ep) { +static bool open_ep_stream_pair(cdch_interface_t * p_cdc, tusb_desc_endpoint_t const * desc_ep) { for (size_t i = 0; i < 2; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); @@ -746,13 +749,13 @@ static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t co tu_edpt_stream_open(&p_cdc->stream.tx, p_cdc->daddr, desc_ep); } - desc_ep = (tusb_desc_endpoint_t const*) tu_desc_next(desc_ep); + desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep); } return true; } -bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { +bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { (void) rhport; cdch_serial_driver_t const * driver_detected = NULL; @@ -826,6 +829,7 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { xfer.user_data = 0; // initial state 0 serial_drivers[p_cdc->serial_drid].process_set_config(&xfer); + return true; } @@ -864,7 +868,7 @@ static void acm_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool acm_set_control_line_state(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_control_line_state(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); tusb_control_request_t const request = { @@ -886,15 +890,16 @@ static bool acm_set_control_line_state(cdch_interface_t* p_cdc, tuh_xfer_cb_t co .ep_addr = 0, .setup = &request, .buffer = NULL, - .complete_cb = complete_cb ? acm_internal_control_complete : NULL, // complete_cb is NULL for sync call + .complete_cb = complete_cb ? acm_internal_control_complete : NULL, .user_data = user_data }; TU_ASSERT(tuh_control_xfer(&xfer)); + return true; } -static bool acm_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); TU_VERIFY(p_cdc->requested_line_coding.data_bits && p_cdc->requested_line_coding.bit_rate); TU_VERIFY((p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8) || @@ -913,30 +918,32 @@ static bool acm_set_line_coding(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_ }; // use usbh enum buf to hold line coding since user line_coding variable does not live long enough - uint8_t* enum_buf = usbh_get_enum_buf(); + uint8_t * enum_buf = usbh_get_enum_buf(); memcpy(enum_buf, &p_cdc->requested_line_coding, sizeof(cdc_line_coding_t)); p_cdc->user_control_cb = complete_cb; + tuh_xfer_t xfer = { .daddr = p_cdc->daddr, .ep_addr = 0, .setup = &request, .buffer = enum_buf, - .complete_cb = complete_cb ? acm_internal_control_complete : NULL, // complete_cb is NULL for sync call + .complete_cb = complete_cb ? acm_internal_control_complete : NULL, .user_data = user_data }; TU_ASSERT(tuh_control_xfer(&xfer)); + return true; } -static bool acm_set_data_format(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->requested_line_coding.bit_rate = p_cdc->line_coding.bit_rate; return acm_set_line_coding(p_cdc, complete_cb, user_data); } -static bool acm_set_baudrate(cdch_interface_t* p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->requested_line_coding.stop_bits = p_cdc->line_coding.stop_bits; p_cdc->requested_line_coding.parity = p_cdc->line_coding.parity; p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits; @@ -952,21 +959,22 @@ enum { CONFIG_ACM_COMPLETE, }; -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len) { - uint8_t const* p_desc_end = ((uint8_t const*) itf_desc) + max_len; +static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { + uint8_t const * p_desc_end = ((uint8_t const *) itf_desc) + max_len; - cdch_interface_t* p_cdc = make_new_itf(daddr, itf_desc); + cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); + p_cdc->serial_drid = SERIAL_DRIVER_ACM; //------------- Control Interface -------------// - uint8_t const* p_desc = tu_desc_next(itf_desc); + uint8_t const * p_desc = tu_desc_next(itf_desc); // Communication Functional Descriptors while ((p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) { if (CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc)) { // save ACM bmCapabilities - p_cdc->acm_capability = ((cdc_desc_func_acm_t const*) p_desc)->bmCapabilities; + p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; } p_desc = tu_desc_next(p_desc); @@ -975,7 +983,7 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint1 // Open notification endpoint of control interface if any if (itf_desc->bNumEndpoints == 1) { TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); - tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) p_desc; + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); p_cdc->ep_notif = desc_ep->bEndpointAddress; @@ -985,22 +993,22 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint1 //------------- Data Interface (if any) -------------// if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const*) p_desc)->bInterfaceClass)) { + (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass)) { // next to endpoint descriptor p_desc = tu_desc_next(p_desc); // data endpoints expected to be in pairs - TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const*) p_desc)); + TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const *) p_desc)); } return true; } -static void acm_process_config(tuh_xfer_t* xfer) { +static void acm_process_config(tuh_xfer_t * xfer) { uintptr_t const state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS, 1); switch (state) { @@ -1814,8 +1822,9 @@ static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t * p_cdc); //------------- Control Request -------------// -static bool ch34x_set_request(cdch_interface_t* p_cdc, uint8_t direction, uint8_t request, uint16_t value, - uint16_t index, uint8_t* buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ch34x_set_request(cdch_interface_t * p_cdc, uint8_t direction, uint8_t request, + uint16_t value, uint16_t index, uint8_t * buffer, uint16_t length, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request_setup = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, @@ -1829,7 +1838,7 @@ static bool ch34x_set_request(cdch_interface_t* p_cdc, uint8_t direction, uint8_ }; // use usbh enum buf since application variable does not live long enough - uint8_t* enum_buf = NULL; + uint8_t * enum_buf = NULL; if (buffer && length > 0) { enum_buf = usbh_get_enum_buf(); @@ -1850,22 +1859,23 @@ static bool ch34x_set_request(cdch_interface_t* p_cdc, uint8_t direction, uint8_ return tuh_control_xfer(&xfer); } -static inline bool ch34x_control_out(cdch_interface_t* p_cdc, uint8_t request, uint16_t value, uint16_t index, +static inline bool ch34x_control_out(cdch_interface_t * p_cdc, uint8_t request, uint16_t value, uint16_t index, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ch34x_set_request(p_cdc, TUSB_DIR_OUT, request, value, index, NULL, 0, complete_cb, user_data); } -static inline bool ch34x_control_in(cdch_interface_t* p_cdc, uint8_t request, uint16_t value, uint16_t index, - uint8_t* buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static inline bool ch34x_control_in(cdch_interface_t * p_cdc, uint8_t request, uint16_t value, uint16_t index, + uint8_t * buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ch34x_set_request(p_cdc, TUSB_DIR_IN, request, value, index, buffer, buffersize, complete_cb, user_data); } -static inline bool ch34x_write_reg(cdch_interface_t* p_cdc, uint16_t reg, uint16_t reg_value, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static inline bool ch34x_write_reg(cdch_interface_t * p_cdc, uint16_t reg, uint16_t reg_value, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, reg, reg_value, complete_cb, user_data); } -//static bool ch34x_read_reg_request ( cdch_interface_t* p_cdc, uint16_t reg, +//static bool ch34x_read_reg_request ( cdch_interface_t * p_cdc, uint16_t reg, // uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) //{ // return ch34x_control_in ( p_cdc, CH34X_REQ_READ_REG, reg, 0, buffer, buffersize, complete_cb, user_data ); @@ -1907,8 +1917,8 @@ static void ch34x_internal_control_complete(tuh_xfer_t * xfer) { // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber uint8_t const itf_num = 0; uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t* p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); TU_LOG_P_CDC("control complete success = %u", success); @@ -1997,17 +2007,17 @@ enum { CONFIG_CH34X_COMPLETE }; -static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uint16_t max_len) { +static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { // CH34x Interface includes 1 vendor interface + 2 bulk + 1 interrupt endpoints - TU_VERIFY (itf_desc->bNumEndpoints == 3); - TU_VERIFY (sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t) <= max_len); + TU_VERIFY(itf_desc->bNumEndpoints == 3); + TU_VERIFY(sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t) <= max_len); - cdch_interface_t* p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY (p_cdc); + cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); + TU_VERIFY(p_cdc); p_cdc->serial_drid = SERIAL_DRIVER_CH34X; - tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) tu_desc_next(itf_desc); + tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); // data endpoints expected to be in pairs TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep)); @@ -2023,11 +2033,11 @@ static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const* itf_desc, uin } static void ch34x_process_config(tuh_xfer_t* xfer) { - // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber uintptr_t const state = xfer->user_data; + // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber uint8_t const itf_num = 0; uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t* p_cdc = get_itf(idx); + cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS); uint8_t buffer[2]; // TODO remove @@ -2035,7 +2045,7 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { case CONFIG_CH34X_READ_VERSION: p_cdc->user_control_cb = ch34x_process_config; // set once for whole process config TU_ASSERT_COMPLETE(ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, - ch34x_process_config, CONFIG_CH34X_SERIAL_INIT)); + ch34x_process_config, CONFIG_CH34X_SERIAL_INIT)); break; case CONFIG_CH34X_SERIAL_INIT: { @@ -2060,19 +2070,20 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { // overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver p_cdc->line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; TU_ASSERT_COMPLETE(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, - ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL)); + ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL)); break; case CONFIG_CH34X_FLOW_CONTROL: // no hardware flow control TU_ASSERT_COMPLETE(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x27, CH341_REG_0x27), 0x0000, - ch34x_process_config, CONFIG_CH34X_MODEM_CONTROL)); + ch34x_process_config, CONFIG_CH34X_MODEM_CONTROL)); break; case CONFIG_CH34X_MODEM_CONTROL: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT_COMPLETE(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE)); + TU_ASSERT_COMPLETE(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, + CONFIG_CH34X_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; @@ -2431,6 +2442,7 @@ static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, u } static void pl2303_process_config(tuh_xfer_t * xfer) { + uintptr_t const state = xfer->user_data; // PL2303 has only interface 0, because wIndex is used as payload and not for bInterfaceNumber uint8_t const itf_num = 0; uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); @@ -2440,7 +2452,7 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { uint8_t buf; int8_t type; - switch (xfer->user_data) { + switch (state) { // from here sequence overtaken from Linux Kernel function pl2303_startup() case CONFIG_PL2303_GET_DESC: From da93fcfc6dbe51ceb73e990aefea9c8d55d3fc94 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 22 Feb 2024 15:09:25 +0100 Subject: [PATCH 018/382] improved TU_LOGs --- src/class/cdc/cdc_host.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 50aa4b6f0..f3fbe88ea 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -50,6 +50,7 @@ DADDR, ITF_NUM, NAME, ##__VA_ARGS__) #define TU_LOG_P_CDC(TXT,...) TU_LOG_CDC(TXT, p_cdc->daddr, p_cdc->bInterfaceNumber, \ serial_drivers[p_cdc->serial_drid].name, ##__VA_ARGS__) +#define TU_LOG_RESULT(TXT,RESULT) TU_LOG_P_CDC(TXT " " #RESULT " = %s", RESULT ? "true" : "FALSE" ) #define TU_ASSERT_COMPLETE_DEFINE(_cond, _itf_offset) \ do { \ @@ -587,6 +588,7 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c if (ret && !complete_cb) { p_cdc->line_state = (uint8_t) line_state; } + TU_LOG_RESULT("set control line state", ret); return ret; } @@ -604,6 +606,7 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete if (ret && !complete_cb) { p_cdc->line_coding.bit_rate = baudrate; } + TU_LOG_RESULT("set baudrate", ret); return ret; } @@ -627,6 +630,7 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin p_cdc->line_coding.parity = parity; p_cdc->line_coding.data_bits = data_bits; } + TU_LOG_RESULT("set data format", ret); return ret; } @@ -646,6 +650,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const * line_coding, if (ret && !complete_cb) { p_cdc->line_coding = *line_coding; } + TU_LOG_RESULT("set line coding", ret); return ret; } @@ -785,6 +790,7 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const * itf_ if (driver_detected) { TU_LOG_CDC("open", daddr, itf_desc->bInterfaceNumber, driver_detected->name); bool ret = driver_detected->open(daddr, itf_desc, max_len); + TU_LOG_CDC("opened ret = %s", daddr, itf_desc->bInterfaceNumber, driver_detected->name, ret ? "true" : "FALSE" ); return ret; } @@ -794,7 +800,7 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const * itf_ static void set_config_complete(uint8_t idx, uint8_t itf_offset, bool success) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); - TU_LOG_P_CDC("set config complete success = %u", success); + TU_LOG_RESULT("set config complete", success); if (success) { p_cdc->mounted = true; @@ -846,7 +852,7 @@ static void acm_internal_control_complete(tuh_xfer_t * xfer) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC("control complete success = %u", success); + TU_LOG_RESULT(" control complete", success); if (success) { switch (xfer->setup->bRequest) { @@ -1131,7 +1137,7 @@ static void ftdi_internal_control_complete(tuh_xfer_t * xfer) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC("control complete success = %u", success); + TU_LOG_RESULT(" control complete", success); if (success) { switch (xfer->setup->bRequest) { @@ -1407,7 +1413,7 @@ static bool ftdi_determine_type(cdch_interface_t * p_cdc, uint8_t const idx) break; } - TU_LOG_P_CDC("%s detected", ftdi_chip_name[p_cdc->ftdi.chip_type]); + TU_LOG_P_CDC(" %s detected", ftdi_chip_name[p_cdc->ftdi.chip_type]); return (p_cdc->ftdi.chip_type != UNKNOWN); } @@ -1554,7 +1560,7 @@ static inline uint32_t ftdi_get_divisor(cdch_interface_t * p_cdc) break; } - TU_LOG_P_CDC("Baudrate divisor 0x%lu", div_value); + TU_LOG_P_CDC(" Baudrate divisor 0x%lu", div_value); return div_value; } @@ -1663,7 +1669,7 @@ static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC("control complete success = %u", success); + TU_LOG_RESULT(" control complete", success); if (success) { switch(xfer->setup->bRequest) { @@ -1920,7 +1926,7 @@ static void ch34x_internal_control_complete(tuh_xfer_t * xfer) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC("control complete success = %u", success); + TU_LOG_RESULT(" control complete", success); if (success) { switch (xfer->setup->bRequest) { @@ -2051,7 +2057,7 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { case CONFIG_CH34X_SERIAL_INIT: { // handle version read data, set CH34x line coding (incl. baudrate) uint8_t const version = xfer->buffer[0]; - TU_LOG_P_CDC("Chip Version = %02x", version); + TU_LOG_P_CDC(" Chip Version = %02x", version); // only versions >= 0x30 are tested, below 0x30 seems having other programming // see drivers from WCH vendor, Linux kernel and FreeBSD TU_ASSERT_COMPLETE(version >= 0x30); @@ -2337,7 +2343,7 @@ static void pl2303_internal_control_complete(tuh_xfer_t * xfer) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC("control complete success = %u", success); + TU_LOG_RESULT(" control complete", success); if (success) { if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && @@ -2743,7 +2749,7 @@ static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t const idx, ui default: break; } - TU_LOG_P_CDC("unknown device type bcdUSB = 0x%04x", desc_dev[idx]->bcdUSB); + TU_LOG_P_CDC(" unknown device type bcdUSB = 0x%04x", desc_dev[idx]->bcdUSB); return PL2303_DETECT_TYPE_FAILED; } @@ -2893,7 +2899,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t * p_cdc, uint8_t buf[PL2303 } else { baud = pl2303_encode_baud_rate_divisor(buf, baud); } - TU_LOG_P_CDC("real baudrate = %lu", baud); + TU_LOG_P_CDC(" real baudrate = %lu", baud); return true; } From 46a861b0e31a7382d620986079abd0c373dfe6da Mon Sep 17 00:00:00 2001 From: IngHK Date: Fri, 23 Feb 2024 08:30:50 +0100 Subject: [PATCH 019/382] improved PL2303 TU_LOGs --- src/class/cdc/cdc_host.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index f3fbe88ea..9d27b1e79 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -2486,13 +2486,14 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { p_cdc->pl2303.serial_private.type = &pl2303_type_data[type]; p_cdc->pl2303.serial_private.quirks |= p_cdc->pl2303.serial_private.type->quirks; #if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL && 0 // can be activated if necessary - TU_LOG(CFG_TUH_CDC_LOG_LEVEL, "PL2303 bDeviceClass = 0x%02x bMaxPacketSize0 = %u bcdUSB = 0x%04x bcdDevice = 0x%04x", - desc_dev[idx]->bDeviceClass, desc_dev[idx]->bMaxPacketSize0, desc_dev[idx]->bcdUSB, desc_dev[idx]->bcdDevice ); + TU_LOG_P_CDC(" bDeviceClass = 0x%02x bMaxPacketSize0 = %u bcdUSB = 0x%04x bcdDevice = 0x%04x", + desc_dev[idx]->bDeviceClass, desc_dev[idx]->bMaxPacketSize0, + desc_dev[idx]->bcdUSB, desc_dev[idx]->bcdDevice ); uint16_t vid, pid; TU_ASSERT_COMPLETE(tuh_vid_pid_get(p_cdc->daddr, &vid, &pid)); - TU_LOG(CFG_TUH_CDC_LOG_LEVEL, " vid = 0x%04x pid = 0x%04x supports_hx_status = %u type = %s quirks = %u", - vid, pid, p_cdc->pl2303.supports_hx_status, - p_cdc->pl2303.serial_private.type->name, p_cdc->pl2303.serial_private.quirks); + TU_LOG_P_CDC(" vid = 0x%04x pid = 0x%04x supports_hx_status = %u type = %s quirks = %u", + vid, pid, p_cdc->pl2303.supports_hx_status, + p_cdc->pl2303.serial_private.type->name, p_cdc->pl2303.serial_private.quirks); #endif // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { From f97e31226a959944785122d4c0c10d4b3304704c Mon Sep 17 00:00:00 2001 From: IngHK Date: Wed, 28 Feb 2024 13:07:40 +0100 Subject: [PATCH 020/382] FTDI fixed itf_num and some improvement --- src/class/cdc/cdc_host.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 9d27b1e79..33d201c07 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -1140,22 +1140,19 @@ static void ftdi_internal_control_complete(tuh_xfer_t * xfer) { TU_LOG_RESULT(" control complete", success); if (success) { - switch (xfer->setup->bRequest) { - case FTDI_SIO_SET_MODEM_CTRL_REQUEST: - p_cdc->line_state = p_cdc->requested_line_state; - break; - - case FTDI_SIO_SET_DATA_REQUEST: - p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; - p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; - p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; - break; - - case FTDI_SIO_SET_BAUDRATE_REQUEST: - p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; - break; - - default: break; + if (xfer->setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST && + xfer->setup->bmRequestType == FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE ) { + p_cdc->line_state = p_cdc->requested_line_state; + } + if (xfer->setup->bRequest == FTDI_SIO_SET_DATA_REQUEST && + xfer->setup->bmRequestType == FTDI_SIO_SET_DATA_REQUEST_TYPE ) { + p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; + p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; + p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; + } + if (xfer->setup->bRequest == FTDI_SIO_SET_BAUDRATE_REQUEST && + xfer->setup->bmRequestType == FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE ) { + p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; } } @@ -1180,7 +1177,10 @@ static bool ftdi_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_c } static void ftdi_set_line_coding_stage1_complete(tuh_xfer_t * xfer) { - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + uint8_t const idx = ftdi_get_idx(xfer); + cdch_interface_t * p_cdc = get_itf(idx); + TU_ASSERT(p_cdc,); + uint8_t const itf_num = p_cdc->bInterfaceNumber; set_line_coding_stage1_complete(xfer, itf_num, ftdi_set_data_request, // control request function to set data format ftdi_internal_control_complete); // control complete function to be called after request @@ -1413,7 +1413,8 @@ static bool ftdi_determine_type(cdch_interface_t * p_cdc, uint8_t const idx) break; } - TU_LOG_P_CDC(" %s detected", ftdi_chip_name[p_cdc->ftdi.chip_type]); + TU_LOG_P_CDC(" %s detected (bcdDevice = 0x%04x)", + ftdi_chip_name[p_cdc->ftdi.chip_type], desc_dev[idx]->bcdDevice); return (p_cdc->ftdi.chip_type != UNKNOWN); } From d3d61da0384d066b9930e8e5b658717983f02efb Mon Sep 17 00:00:00 2001 From: IngHK Date: Sun, 25 Feb 2024 17:20:02 +0100 Subject: [PATCH 021/382] improved & fixed compiler warnings device descriptor handling --- src/class/cdc/cdc_host.c | 44 +++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 33d201c07..c222e11db 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -111,8 +111,10 @@ typedef struct { CFG_TUH_MEM_SECTION static cdch_interface_t cdch_data[CFG_TUH_CDC]; + #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_PL2303 - static tusb_desc_device_t desc_dev[CFG_TUH_CDC][CFG_TUH_ENUMERATION_BUFSIZE]; + CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN + static tusb_desc_device_t desc_dev[CFG_TUH_ENUMERATION_BUFSIZE]; #endif //--------------------------------------------------------------------+ @@ -1054,7 +1056,7 @@ static void acm_process_config(tuh_xfer_t * xfer) { //--------------------------------------------------------------------+ #if CFG_TUH_CDC_FTDI -static bool ftdi_determine_type(cdch_interface_t * p_cdc, uint8_t const idx); +static bool ftdi_determine_type(cdch_interface_t * p_cdc); static uint32_t ftdi_get_divisor(cdch_interface_t * p_cdc); static uint8_t ftdi_get_idx(tuh_xfer_t * xfer); @@ -1255,7 +1257,7 @@ static void ftdi_process_config(tuh_xfer_t * xfer) { // get device descriptor p_cdc->user_control_cb = ftdi_process_config; // set once for whole process config if (itf_num == 0) { // only necessary for 1st interface. other interface overtake type from interface 0 - TU_ASSERT_COMPLETE(tuh_descriptor_get_device(xfer->daddr, desc_dev[idx], sizeof(tusb_desc_device_t), + TU_ASSERT_COMPLETE(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), ftdi_process_config, CONFIG_FTDI_DETERMINE_TYPE)); break; } @@ -1264,7 +1266,7 @@ static void ftdi_process_config(tuh_xfer_t * xfer) { case CONFIG_FTDI_DETERMINE_TYPE: // determine type if (itf_num == 0) { - TU_ASSERT_COMPLETE(ftdi_determine_type(p_cdc, idx)); + TU_ASSERT_COMPLETE(ftdi_determine_type(p_cdc)); } else { // other interfaces have same type as interface 0 uint8_t const idx_itf0 = tuh_cdc_itf_get_index(xfer->daddr, 0); @@ -1334,9 +1336,9 @@ static void ftdi_process_config(tuh_xfer_t * xfer) { //------------- Helper -------------// -static bool ftdi_determine_type(cdch_interface_t * p_cdc, uint8_t const idx) +static bool ftdi_determine_type(cdch_interface_t * p_cdc) { - uint16_t const version = desc_dev[idx]->bcdDevice; + uint16_t const version = desc_dev->bcdDevice; uint8_t const itf_num = p_cdc->bInterfaceNumber; p_cdc->ftdi.chip_type = UNKNOWN; @@ -1414,7 +1416,7 @@ static bool ftdi_determine_type(cdch_interface_t * p_cdc, uint8_t const idx) } TU_LOG_P_CDC(" %s detected (bcdDevice = 0x%04x)", - ftdi_chip_name[p_cdc->ftdi.chip_type], desc_dev[idx]->bcdDevice); + ftdi_chip_name[p_cdc->ftdi.chip_type], desc_dev->bcdDevice); return (p_cdc->ftdi.chip_type != UNKNOWN); } @@ -2207,7 +2209,7 @@ static uint8_t ch34x_get_lcr(cdch_interface_t * p_cdc) { //--------------------------------------------------------------------+ #if CFG_TUH_CDC_PL2303 -static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t const idx, uint8_t step, +static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t step, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool pl2303_encode_baud_rate(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]); @@ -2465,13 +2467,13 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { case CONFIG_PL2303_GET_DESC: p_cdc->user_control_cb = pl2303_process_config; // set once for whole process config // get device descriptor - TU_ASSERT_COMPLETE(tuh_descriptor_get_device(xfer->daddr, desc_dev[idx], sizeof(tusb_desc_device_t), + TU_ASSERT_COMPLETE(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), pl2303_process_config, CONFIG_PL2303_DETECT_TYPE)); break; case CONFIG_PL2303_DETECT_TYPE: // get type and quirks (step 1) - type = pl2303_detect_type (p_cdc, idx, 1, pl2303_process_config, CONFIG_PL2303_READ1); // step 1 + type = pl2303_detect_type (p_cdc, 1, pl2303_process_config, CONFIG_PL2303_READ1); // step 1 TU_ASSERT_COMPLETE(type!=PL2303_DETECT_TYPE_FAILED); if (type == PL2303_SUPPORTS_HX_STATUS_TRIGGERED) { break; @@ -2482,14 +2484,14 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { // get supports_hx_status, type and quirks (step 2), do special read p_cdc->pl2303.supports_hx_status = ( // will not be true, if coming directly from previous case xfer->user_data == CONFIG_PL2303_READ1 && xfer->result == XFER_RESULT_SUCCESS ); - type = pl2303_detect_type (p_cdc, idx, 2, NULL, 0); // step 2 now with supports_hx_status + type = pl2303_detect_type (p_cdc, 2, NULL, 0); // step 2 now with supports_hx_status TU_ASSERT_COMPLETE(type!=PL2303_DETECT_TYPE_FAILED); p_cdc->pl2303.serial_private.type = &pl2303_type_data[type]; p_cdc->pl2303.serial_private.quirks |= p_cdc->pl2303.serial_private.type->quirks; #if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL && 0 // can be activated if necessary TU_LOG_P_CDC(" bDeviceClass = 0x%02x bMaxPacketSize0 = %u bcdUSB = 0x%04x bcdDevice = 0x%04x", - desc_dev[idx]->bDeviceClass, desc_dev[idx]->bMaxPacketSize0, - desc_dev[idx]->bcdUSB, desc_dev[idx]->bcdDevice ); + desc_dev->bDeviceClass, desc_dev->bMaxPacketSize0, + desc_dev->bcdUSB, desc_dev->bcdDevice ); uint16_t vid, pid; TU_ASSERT_COMPLETE(tuh_vid_pid_get(p_cdc->daddr, &vid, &pid)); TU_LOG_P_CDC(" vid = 0x%04x pid = 0x%04x supports_hx_status = %u type = %s quirks = %u", @@ -2674,29 +2676,29 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { //------------- Helper -------------// -static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t const idx, uint8_t step, +static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t step, tuh_xfer_cb_t complete_cb, uintptr_t user_data ) { /* * Legacy PL2303H, variants 0 and 1 (difference unknown). */ - if (desc_dev[idx]->bDeviceClass == 0x02) { + if (desc_dev->bDeviceClass == 0x02) { return TYPE_H; /* variant 0 */ } - if (desc_dev[idx]->bMaxPacketSize0 != 0x40) { - if (desc_dev[idx]->bDeviceClass == 0x00 || desc_dev[idx]->bDeviceClass == 0xff) { + if (desc_dev->bMaxPacketSize0 != 0x40) { + if (desc_dev->bDeviceClass == 0x00 || desc_dev->bDeviceClass == 0xff) { return TYPE_H; /* variant 1 */ } return TYPE_H; /* variant 0 */ } - switch (desc_dev[idx]->bcdUSB) { + switch (desc_dev->bcdUSB) { case 0x101: /* USB 1.0.1? Let's assume they meant 1.1... */ TU_ATTR_FALLTHROUGH; case 0x110: - switch (desc_dev[idx]->bcdDevice) { + switch (desc_dev->bcdDevice) { case 0x300: return TYPE_HX; case 0x400: @@ -2706,7 +2708,7 @@ static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t const idx, ui } break; case 0x200: - switch (desc_dev[idx]->bcdDevice) { + switch (desc_dev->bcdDevice) { case 0x100: /* GC */ case 0x105: return TYPE_HXN; @@ -2751,7 +2753,7 @@ static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t const idx, ui default: break; } - TU_LOG_P_CDC(" unknown device type bcdUSB = 0x%04x", desc_dev[idx]->bcdUSB); + TU_LOG_P_CDC(" unknown device type bcdUSB = 0x%04x", desc_dev->bcdUSB); return PL2303_DETECT_TYPE_FAILED; } From edf13203916931962a53af50abc548dd3eded278 Mon Sep 17 00:00:00 2001 From: IngHK Date: Wed, 28 Feb 2024 13:13:18 +0100 Subject: [PATCH 022/382] removed expendable ACM check --- src/class/cdc/cdc_host.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index c222e11db..4d2134f9d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -909,7 +909,6 @@ static bool acm_set_control_line_state(cdch_interface_t * p_cdc, tuh_xfer_cb_t c static bool acm_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); - TU_VERIFY(p_cdc->requested_line_coding.data_bits && p_cdc->requested_line_coding.bit_rate); TU_VERIFY((p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8) || p_cdc->requested_line_coding.data_bits == 16); From 3cf9cb98e630a0cb26bc28a2e4c67fb6df19a884 Mon Sep 17 00:00:00 2001 From: IngHK Date: Wed, 28 Feb 2024 13:15:37 +0100 Subject: [PATCH 023/382] small PL2303 improvements --- src/class/cdc/cdc_host.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 4d2134f9d..130993547 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -2292,9 +2292,10 @@ static bool pl2303_set_line_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t comp * even to the same values as before. Thus we actually need to filter * in this specific case. */ - // TODO really necessary to check? what to do in this case when no transfer will happen? - // callback is not called... - TU_VERIFY(memcmp(&p_cdc->requested_line_coding, &p_cdc->line_coding, sizeof(cdc_line_coding_t) ) != 0); + TU_VERIFY(p_cdc->requested_line_coding.data_bits != p_cdc->line_coding.data_bits || + p_cdc->requested_line_coding.stop_bits != p_cdc->line_coding.stop_bits || + p_cdc->requested_line_coding.parity != p_cdc->line_coding.parity || + p_cdc->requested_line_coding.bit_rate != p_cdc->line_coding.bit_rate ); /* For reference buf[6] data bits value */ TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8, 0); From e7308e313a1fb5482dbbb34cdfc6b7b11a54fd6b Mon Sep 17 00:00:00 2001 From: IngHK Date: Wed, 28 Feb 2024 13:28:38 +0100 Subject: [PATCH 024/382] improved TU_LOGs --- src/class/cdc/cdc.h | 12 ++++++++ src/class/cdc/cdc_host.c | 65 ++++++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 5cbd658fe..b1dca1ad8 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -192,6 +192,11 @@ typedef enum { CDC_LINE_CODING_STOP_BITS_2 = 2, // 2 bits } cdc_line_coding_stopbits_t; +#define CDC_LINE_CODING_STOP_BITS_TEXT(STOP_BITS) ( \ + STOP_BITS == CDC_LINE_CODING_STOP_BITS_1 ? "1" : \ + STOP_BITS == CDC_LINE_CODING_STOP_BITS_1_5 ? "1.5" : \ + STOP_BITS == CDC_LINE_CODING_STOP_BITS_2 ? "2" : "?" ) + // TODO Backward compatible for typos. Maybe removed in the future release #define CDC_LINE_CONDING_STOP_BITS_1 CDC_LINE_CODING_STOP_BITS_1 #define CDC_LINE_CONDING_STOP_BITS_1_5 CDC_LINE_CODING_STOP_BITS_1_5 @@ -205,6 +210,13 @@ typedef enum { CDC_LINE_CODING_PARITY_SPACE = 4, } cdc_line_coding_parity_t; +#define CDC_LINE_CODING_PARITY_CHAR(PARITY) ( \ + PARITY == CDC_LINE_CODING_PARITY_NONE ? 'N' : \ + PARITY == CDC_LINE_CODING_PARITY_ODD ? 'O' : \ + PARITY == CDC_LINE_CODING_PARITY_EVEN ? 'E' : \ + PARITY == CDC_LINE_CODING_PARITY_MARK ? 'M' : \ + PARITY == CDC_LINE_CODING_PARITY_SPACE ? 'S' : '?' ) + //--------------------------------------------------------------------+ // Management Element Notification (Notification Endpoint) //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 130993547..d2bc63d64 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -50,7 +50,7 @@ DADDR, ITF_NUM, NAME, ##__VA_ARGS__) #define TU_LOG_P_CDC(TXT,...) TU_LOG_CDC(TXT, p_cdc->daddr, p_cdc->bInterfaceNumber, \ serial_drivers[p_cdc->serial_drid].name, ##__VA_ARGS__) -#define TU_LOG_RESULT(TXT,RESULT) TU_LOG_P_CDC(TXT " " #RESULT " = %s", RESULT ? "true" : "FALSE" ) +#define TU_LOG_P_CDC_BOOL(TXT,VAL) TU_LOG_P_CDC(TXT " " #VAL " = %s", VAL ? "true" : "false" ) #define TU_ASSERT_COMPLETE_DEFINE(_cond, _itf_offset) \ do { \ @@ -395,14 +395,20 @@ bool tuh_cdc_get_dtr(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_DTR) ? true : false; + bool ret = (p_cdc->line_state & CDC_CONTROL_LINE_STATE_DTR); +// TU_LOG_P_CDC_BOOL("get DTR", ret); + + return ret; } bool tuh_cdc_get_rts(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return (p_cdc->line_state & CDC_CONTROL_LINE_STATE_RTS) ? true : false; + bool ret = (p_cdc->line_state & CDC_CONTROL_LINE_STATE_RTS); +// TU_LOG_P_CDC_BOOL("get RTS", ret); + + return ret; } bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t * line_coding) { @@ -410,6 +416,10 @@ bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t * line_coding) TU_VERIFY(p_cdc); *line_coding = p_cdc->line_coding; + TU_LOG_P_CDC("get line coding %lu %u%c%s", + p_cdc->line_coding.bit_rate, p_cdc->line_coding.data_bits, + CDC_LINE_CODING_PARITY_CHAR(p_cdc->line_coding.parity), + CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); return true; } @@ -590,7 +600,7 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c if (ret && !complete_cb) { p_cdc->line_state = (uint8_t) line_state; } - TU_LOG_RESULT("set control line state", ret); +// TU_LOG_P_CDC_BOOL("set control line state", ret); return ret; } @@ -598,7 +608,7 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set baudrate = %lu", baudrate); + TU_LOG_P_CDC("set baudrate %lu", baudrate); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line_coding.bit_rate = baudrate; @@ -608,7 +618,7 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete if (ret && !complete_cb) { p_cdc->line_coding.bit_rate = baudrate; } - TU_LOG_RESULT("set baudrate", ret); +// TU_LOG_P_CDC_BOOL("set baudrate", ret); return ret; } @@ -617,8 +627,9 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set data format data_bits = %u parity = %u stop_bits = %u (indexes!)", - data_bits, parity, stop_bits); + TU_LOG_P_CDC("set data format %u%c%s", + data_bits, CDC_LINE_CODING_PARITY_CHAR(parity), + CDC_LINE_CODING_STOP_BITS_TEXT(stop_bits)); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line_coding.stop_bits = stop_bits; @@ -632,7 +643,7 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin p_cdc->line_coding.parity = parity; p_cdc->line_coding.data_bits = data_bits; } - TU_LOG_RESULT("set data format", ret); +// TU_LOG_P_CDC_BOOL("set data format", ret); return ret; } @@ -641,8 +652,10 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const * line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set line coding baudrate = %lu data_bits = %u parity = %u stop_bits = %u (indexes!)", - line_coding->bit_rate, line_coding->data_bits, line_coding->parity, line_coding->stop_bits); + TU_LOG_P_CDC("set line coding %lu %u%c%s", + line_coding->bit_rate, line_coding->data_bits, + CDC_LINE_CODING_PARITY_CHAR(line_coding->parity), + CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line_coding = *line_coding; @@ -652,7 +665,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const * line_coding, if (ret && !complete_cb) { p_cdc->line_coding = *line_coding; } - TU_LOG_RESULT("set line coding", ret); +// TU_LOG_P_CDC_BOOL("set line coding", ret); return ret; } @@ -792,7 +805,7 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const * itf_ if (driver_detected) { TU_LOG_CDC("open", daddr, itf_desc->bInterfaceNumber, driver_detected->name); bool ret = driver_detected->open(daddr, itf_desc, max_len); - TU_LOG_CDC("opened ret = %s", daddr, itf_desc->bInterfaceNumber, driver_detected->name, ret ? "true" : "FALSE" ); +// TU_LOG_CDC("opened ret = %s", daddr, itf_desc->bInterfaceNumber, driver_detected->name, ret ? "true" : "FALSE" ); return ret; } @@ -802,7 +815,7 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const * itf_ static void set_config_complete(uint8_t idx, uint8_t itf_offset, bool success) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); - TU_LOG_RESULT("set config complete", success); + TU_LOG_P_CDC_BOOL("set config complete", success); if (success) { p_cdc->mounted = true; @@ -854,7 +867,7 @@ static void acm_internal_control_complete(tuh_xfer_t * xfer) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_RESULT(" control complete", success); + TU_LOG_P_CDC_BOOL("control complete", success); if (success) { switch (xfer->setup->bRequest) { @@ -1138,7 +1151,7 @@ static void ftdi_internal_control_complete(tuh_xfer_t * xfer) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_RESULT(" control complete", success); + TU_LOG_P_CDC_BOOL("control complete", success); if (success) { if (xfer->setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST && @@ -1414,7 +1427,7 @@ static bool ftdi_determine_type(cdch_interface_t * p_cdc) break; } - TU_LOG_P_CDC(" %s detected (bcdDevice = 0x%04x)", + TU_LOG_P_CDC("%s detected (bcdDevice = 0x%04x)", ftdi_chip_name[p_cdc->ftdi.chip_type], desc_dev->bcdDevice); return (p_cdc->ftdi.chip_type != UNKNOWN); @@ -1562,7 +1575,7 @@ static inline uint32_t ftdi_get_divisor(cdch_interface_t * p_cdc) break; } - TU_LOG_P_CDC(" Baudrate divisor 0x%lu", div_value); + TU_LOG_P_CDC("Baudrate divisor = 0x%lu", div_value); return div_value; } @@ -1671,7 +1684,7 @@ static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_RESULT(" control complete", success); + TU_LOG_P_CDC_BOOL("control complete", success); if (success) { switch(xfer->setup->bRequest) { @@ -1928,7 +1941,7 @@ static void ch34x_internal_control_complete(tuh_xfer_t * xfer) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_RESULT(" control complete", success); + TU_LOG_P_CDC_BOOL("control complete", success); if (success) { switch (xfer->setup->bRequest) { @@ -2059,7 +2072,7 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { case CONFIG_CH34X_SERIAL_INIT: { // handle version read data, set CH34x line coding (incl. baudrate) uint8_t const version = xfer->buffer[0]; - TU_LOG_P_CDC(" Chip Version = %02x", version); + TU_LOG_P_CDC("Chip Version = 0x%02x", version); // only versions >= 0x30 are tested, below 0x30 seems having other programming // see drivers from WCH vendor, Linux kernel and FreeBSD TU_ASSERT_COMPLETE(version >= 0x30); @@ -2346,7 +2359,7 @@ static void pl2303_internal_control_complete(tuh_xfer_t * xfer) { cdch_interface_t * p_cdc = get_itf(idx); TU_ASSERT(p_cdc,); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_RESULT(" control complete", success); + TU_LOG_P_CDC_BOOL("control complete", success); if (success) { if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && @@ -2489,12 +2502,12 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { p_cdc->pl2303.serial_private.type = &pl2303_type_data[type]; p_cdc->pl2303.serial_private.quirks |= p_cdc->pl2303.serial_private.type->quirks; #if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL && 0 // can be activated if necessary - TU_LOG_P_CDC(" bDeviceClass = 0x%02x bMaxPacketSize0 = %u bcdUSB = 0x%04x bcdDevice = 0x%04x", + TU_LOG_P_CDC("bDeviceClass = 0x%02x bMaxPacketSize0 = %u bcdUSB = 0x%04x bcdDevice = 0x%04x", desc_dev->bDeviceClass, desc_dev->bMaxPacketSize0, desc_dev->bcdUSB, desc_dev->bcdDevice ); uint16_t vid, pid; TU_ASSERT_COMPLETE(tuh_vid_pid_get(p_cdc->daddr, &vid, &pid)); - TU_LOG_P_CDC(" vid = 0x%04x pid = 0x%04x supports_hx_status = %u type = %s quirks = %u", + TU_LOG_P_CDC("vid = 0x%04x pid = 0x%04x supports_hx_status = %u type = %s quirks = %u", vid, pid, p_cdc->pl2303.supports_hx_status, p_cdc->pl2303.serial_private.type->name, p_cdc->pl2303.serial_private.quirks); #endif @@ -2753,7 +2766,7 @@ static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t step, default: break; } - TU_LOG_P_CDC(" unknown device type bcdUSB = 0x%04x", desc_dev->bcdUSB); + TU_LOG_P_CDC("unknown device type bcdUSB = 0x%04x", desc_dev->bcdUSB); return PL2303_DETECT_TYPE_FAILED; } @@ -2903,7 +2916,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t * p_cdc, uint8_t buf[PL2303 } else { baud = pl2303_encode_baud_rate_divisor(buf, baud); } - TU_LOG_P_CDC(" real baudrate = %lu", baud); + TU_LOG_P_CDC("real baudrate %lu", baud); return true; } From e6d27b6d3e8fc928cc00ab08898243c7e037ba35 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 29 Feb 2024 20:19:35 +0100 Subject: [PATCH 025/382] fixed IAR compile error --- src/class/cdc/cdc_host.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index d2bc63d64..dfe078de4 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -113,7 +113,6 @@ CFG_TUH_MEM_SECTION static cdch_interface_t cdch_data[CFG_TUH_CDC]; #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_PL2303 - CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static tusb_desc_device_t desc_dev[CFG_TUH_ENUMERATION_BUFSIZE]; #endif From dea27d28bceeaaa23d3daa6468373cb536390108 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 29 Feb 2024 20:24:13 +0100 Subject: [PATCH 026/382] added explicite (uint16_t) casts inside tu_htole16() --- src/class/cdc/cdc_host.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index dfe078de4..d71cda124 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -932,8 +932,8 @@ static bool acm_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete }, .bRequest = CDC_REQUEST_SET_LINE_CODING, .wValue = 0, - .wIndex = tu_htole16(p_cdc->bInterfaceNumber), - .wLength = tu_htole16(sizeof(cdc_line_coding_t)) + .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), + .wLength = tu_htole16((uint16_t) sizeof(cdc_line_coding_t)) }; // use usbh enum buf to hold line coding since user line_coding variable does not live long enough @@ -1612,7 +1612,7 @@ static bool cp210x_set_request(cdch_interface_t * p_cdc, uint8_t command, uint16 }, .bRequest = command, .wValue = tu_htole16(value), - .wIndex = tu_htole16(p_cdc->bInterfaceNumber), + .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), .wLength = tu_htole16(length) }; @@ -1852,9 +1852,9 @@ static bool ch34x_set_request(cdch_interface_t * p_cdc, uint8_t direction, uint8 .direction = direction & 0x01u }, .bRequest = request, - .wValue = tu_htole16 (value), - .wIndex = tu_htole16 (index), - .wLength = tu_htole16 (length) + .wValue = tu_htole16(value), + .wIndex = tu_htole16(index), + .wLength = tu_htole16(length) }; // use usbh enum buf since application variable does not live long enough @@ -2232,9 +2232,9 @@ static bool pl2303_set_request(cdch_interface_t * p_cdc, uint8_t request, uint8_ tusb_control_request_t const request_setup = { .bmRequestType = requesttype, .bRequest = request, - .wValue = tu_htole16 (value), - .wIndex = tu_htole16 (index), - .wLength = tu_htole16 (length) + .wValue = tu_htole16(value), + .wIndex = tu_htole16(index), + .wLength = tu_htole16(length) }; // use usbh enum buf since application variable does not live long enough From e0551043ca8a6b3be92fed57f5e34d6d8014406b Mon Sep 17 00:00:00 2001 From: IngHK Date: Sun, 3 Mar 2024 13:02:58 +0100 Subject: [PATCH 027/382] added use of cdc_line_control_state_t type in CDCh --- src/class/cdc/cdc.h | 14 +++++++----- src/class/cdc/cdc_device.c | 2 ++ src/class/cdc/cdc_host.c | 45 ++++++++++++++++---------------------- 3 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index b1dca1ad8..10aed79ab 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -414,15 +414,17 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); -typedef struct TU_ATTR_PACKED +typedef union TU_ATTR_PACKED { - uint16_t dtr : 1; - uint16_t rts : 1; - uint16_t : 6; - uint16_t : 8; + struct { + uint8_t dtr : 1; + uint8_t rts : 1; + uint8_t : 6; + }; + uint8_t all; } cdc_line_control_state_t; -TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); +TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 1, "size is not correct"); TU_ATTR_PACKED_END // End of all packed definitions TU_ATTR_BIT_FIELD_ORDER_END diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index c26264e60..9f51a6d4b 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -56,6 +56,7 @@ typedef struct uint8_t ep_out; // Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) + // TODO use cdc_line_control_state_t instead of uint8_t uint8_t line_state; /*------------- From this point, data is not cleared by bus reset -------------*/ @@ -124,6 +125,7 @@ bool tud_cdc_n_connected(uint8_t itf) } uint8_t tud_cdc_n_get_line_state (uint8_t itf) +// TODO use cdc_line_control_state_t instead of uint8_t { return _cdcd_itf[itf].line_state; } diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index d71cda124..a3407a5f9 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -81,8 +81,8 @@ typedef struct { TU_ATTR_ALIGNED(4) cdc_line_coding_t requested_line_coding; // 1 byte padding - uint8_t line_state; // DTR (bit0), RTS (bit1) - uint8_t requested_line_state; + cdc_line_control_state_t line_state; + cdc_line_control_state_t requested_line_state; tuh_xfer_cb_t user_control_cb; #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X @@ -339,7 +339,7 @@ static cdch_interface_t * make_new_itf(uint8_t daddr, tusb_desc_interface_t cons p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass; p_cdc->bInterfaceProtocol = itf_desc->bInterfaceProtocol; p_cdc->line_coding = (cdc_line_coding_t) { 0, 0, 0, 0 }; - p_cdc->line_state = 0; + p_cdc->line_state.all = 0; return p_cdc; } } @@ -394,7 +394,7 @@ bool tuh_cdc_get_dtr(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - bool ret = (p_cdc->line_state & CDC_CONTROL_LINE_STATE_DTR); + bool ret = p_cdc->line_state.dtr; // TU_LOG_P_CDC_BOOL("get DTR", ret); return ret; @@ -404,7 +404,7 @@ bool tuh_cdc_get_rts(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - bool ret = (p_cdc->line_state & CDC_CONTROL_LINE_STATE_RTS); + bool ret = p_cdc->line_state.rts; // TU_LOG_P_CDC_BOOL("get RTS", ret); return ret; @@ -592,12 +592,12 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c TU_LOG_P_CDC("set control line state line_state = %u", line_state); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; - p_cdc->requested_line_state = (uint8_t) line_state; + p_cdc->requested_line_state.all = (uint8_t) line_state; bool ret = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data); if (ret && !complete_cb) { - p_cdc->line_state = (uint8_t) line_state; + p_cdc->line_state.all = (uint8_t) line_state; } // TU_LOG_P_CDC_BOOL("set control line state", ret); @@ -898,7 +898,7 @@ static bool acm_set_control_line_state(cdch_interface_t * p_cdc, tuh_xfer_cb_t c .direction = TUSB_DIR_OUT }, .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = tu_htole16(p_cdc->requested_line_state), + .wValue = tu_htole16((uint16_t) p_cdc->requested_line_state.all), .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), .wLength = 0 }; @@ -1034,7 +1034,7 @@ static void acm_process_config(tuh_xfer_t * xfer) { case CONFIG_ACM_SET_CONTROL_LINE_STATE: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM if (p_cdc->acm_capability.support_line_request) { - p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + p_cdc->requested_line_state.all = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(acm_set_control_line_state(p_cdc, acm_process_config, CONFIG_ACM_SET_LINE_CODING), 1); break; } @@ -1139,7 +1139,7 @@ static bool ftdi_set_data_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t comple static inline bool ftdi_update_mctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // FTDI has the same bit coding return ftdi_set_request(p_cdc, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - p_cdc->requested_line_state, p_cdc->ftdi.channel, complete_cb, user_data); + p_cdc->requested_line_state.all, p_cdc->ftdi.channel, complete_cb, user_data); } //------------- Driver API -------------// @@ -1328,7 +1328,7 @@ static void ftdi_process_config(tuh_xfer_t * xfer) { case CONFIG_FTDI_MODEM_CTRL: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + p_cdc->requested_line_state.all = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_COMPLETE)); break; #else @@ -1670,7 +1670,7 @@ static inline bool cp210x_set_mhs(cdch_interface_t * p_cdc, tuh_xfer_cb_t comple // CP210x has the same bit coding return cp210x_set_request(p_cdc, CP210X_SET_MHS, (uint16_t) ((uint32_t) CP210X_CONTROL_WRITE_DTR | - (uint32_t) CP210X_CONTROL_WRITE_RTS | p_cdc->requested_line_state), + (uint32_t) CP210X_CONTROL_WRITE_RTS | p_cdc->requested_line_state.all), NULL, 0, complete_cb, user_data); } @@ -1811,7 +1811,7 @@ static void cp210x_process_config(tuh_xfer_t * xfer) { case CONFIG_CP210X_SET_DTR_RTS: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + p_cdc->requested_line_state.all = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_COMPLETE)); break; @@ -1916,16 +1916,8 @@ static bool ch34x_write_reg_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t com } static bool ch34x_modem_ctrl_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t control = 0; - if (p_cdc->requested_line_state & CDC_CONTROL_LINE_STATE_RTS) { - control |= CH34X_BIT_RTS; - } - if (p_cdc->requested_line_state & CDC_CONTROL_LINE_STATE_DTR) { - control |= CH34X_BIT_DTR; - } - - // CH34x signals are inverted - control = ~control; + uint8_t control = ~((p_cdc->requested_line_state.rts ? CH34X_BIT_RTS : 0) | // CH34x signals are inverted + (p_cdc->requested_line_state.dtr ? CH34X_BIT_DTR : 0)); return ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, complete_cb, user_data); } @@ -2101,7 +2093,7 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { case CONFIG_CH34X_MODEM_CONTROL: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + p_cdc->requested_line_state.all = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE)); break; @@ -2287,8 +2279,9 @@ static inline bool pl2303_supports_hx_status(cdch_interface_t * p_cdc, tuh_xfer_ static inline bool pl2303_set_control_lines(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // PL2303 has the same bit coding return pl2303_set_request(p_cdc, PL2303_SET_CONTROL_REQUEST, PL2303_SET_CONTROL_REQUEST_TYPE, - p_cdc->requested_line_state, 0, NULL, 0, complete_cb, user_data); + p_cdc->requested_line_state.all, 0, NULL, 0, complete_cb, user_data); } //static bool pl2303_get_line_request(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BUFSIZE]) @@ -2645,7 +2638,7 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { case CONFIG_PL2303_MODEM_CONTROL: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + p_cdc->requested_line_state.all = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_FLOW_CTRL_READ)); break; #else From a9cc07fc83599fab4d9576e6f5b793bc1bf2bf35 Mon Sep 17 00:00:00 2001 From: IngHK Date: Sun, 10 Mar 2024 08:20:12 +0100 Subject: [PATCH 028/382] added line control function using cdc_line_control_state_t --- src/class/cdc/cdc_host.c | 35 ++++++++++++++++++++++++++++++----- src/class/cdc/cdc_host.h | 10 ++++++++-- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index a3407a5f9..86b874b1e 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -50,8 +50,9 @@ DADDR, ITF_NUM, NAME, ##__VA_ARGS__) #define TU_LOG_P_CDC(TXT,...) TU_LOG_CDC(TXT, p_cdc->daddr, p_cdc->bInterfaceNumber, \ serial_drivers[p_cdc->serial_drid].name, ##__VA_ARGS__) -#define TU_LOG_P_CDC_BOOL(TXT,VAL) TU_LOG_P_CDC(TXT " " #VAL " = %s", VAL ? "true" : "false" ) +#define TU_LOG_P_CDC_BOOL(TXT,VAL) TU_LOG_P_CDC(TXT " " #VAL " = %d", VAL) +// assert and set config complete #define TU_ASSERT_COMPLETE_DEFINE(_cond, _itf_offset) \ do { \ if (!(_cond)) { _MESS_FAILED(); TU_BREAKPOINT(); set_config_complete(idx, _itf_offset, false); } \ @@ -586,24 +587,48 @@ static bool set_function_call ( } } -bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +bool tuh_cdc_set_control_line_state_u(uint8_t idx, cdc_line_control_state_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // uses cdc_line_control_state_t union for line_state cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set control line state line_state = %u", line_state); + TU_LOG_P_CDC("set control line state dtr = %u rts = %u", line_state.dtr, line_state.rts ); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; - p_cdc->requested_line_state.all = (uint8_t) line_state; + p_cdc->requested_line_state = line_state; bool ret = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data); if (ret && !complete_cb) { - p_cdc->line_state.all = (uint8_t) line_state; + p_cdc->line_state = line_state; } // TU_LOG_P_CDC_BOOL("set control line state", ret); return ret; } +bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + // uses uint16_t for line_state => DTR (bit 0), RTS (bit 1) + + return tuh_cdc_set_control_line_state_u(idx, (cdc_line_control_state_t) { .all = (uint8_t) line_state }, + complete_cb, user_data); +} + +bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + cdch_interface_t * p_cdc = get_itf(idx); + TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + cdc_line_control_state_t const line_state = { .dtr = dtr_state, .rts = p_cdc->line_state.rts }; + + return tuh_cdc_set_control_line_state_u(idx, line_state, complete_cb, user_data); +} + +bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + cdch_interface_t * p_cdc = get_itf(idx); + TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + cdc_line_control_state_t const line_state = { .rts = rts_state, .dtr = p_cdc->line_state.dtr }; + + return tuh_cdc_set_control_line_state_u(idx, line_state, complete_cb, user_data); +} + bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index ca6567453..77081d3b0 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -132,8 +132,14 @@ bool tuh_cdc_read_clear (uint8_t idx); // - The function will return true if transfer is successful, false otherwise. //--------------------------------------------------------------------+ -// Request to Set Control Line State: DTR (bit 0), RTS (bit 1) -bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +// Request to Set Control Line State +bool tuh_cdc_set_control_line_state_u(uint8_t idx, cdc_line_control_state_t line_state, // uses cdc_line_control_state_t union for line_state + tuh_xfer_cb_t complete_cb, uintptr_t user_data); +bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, // uses uint16_t for line_state (legacy function) + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // DTR (bit 0), RTS (bit 1) + +bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set DTR +bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set RTS // Request to set baudrate bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); From ee92e582b38e36df53381f8c98a0be54c2caef3e Mon Sep 17 00:00:00 2001 From: IngHK Date: Sun, 3 Mar 2024 13:12:10 +0100 Subject: [PATCH 029/382] added defines CFG_TUH_CDC_DTR_CONTROL_ON_ENUM & CFG_TUH_CDC_RTS_CONTROL_ON_ENUM --- examples/host/cdc_msc_hid/src/tusb_config.h | 4 +- .../cdc_msc_hid_freertos/src/tusb_config.h | 4 +- src/class/cdc/cdc_host.c | 40 ++++++++++++++----- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index fc956c6d3..32a29bd4f 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -121,8 +121,8 @@ //------------- CDC -------------// // Set Line Control state on enumeration/mounted: -// DTR ( bit 0), RTS (bit 1) -#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0x03 +#define CFG_TUH_CDC_DTR_CONTROL_ON_ENUM true +#define CFG_TUH_CDC_RTS_CONTROL_ON_ENUM true // Set Line Coding on enumeration/mounted, value for cdc_line_coding_t // bit rate = 115200, 1 stop bit, no parity, 8 bit data width diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index dd732c700..88b341e95 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -126,8 +126,8 @@ //------------- CDC -------------// // Set Line Control state on enumeration/mounted: -// DTR ( bit 0), RTS (bit 1) -#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0x03 +#define CFG_TUH_CDC_DTR_CONTROL_ON_ENUM true +#define CFG_TUH_CDC_RTS_CONTROL_ON_ENUM true // Set Line Coding on enumeration/mounted, value for cdc_line_coding_t // bit rate = 115200, 1 stop bit, no parity, 8 bit data width diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 86b874b1e..5b74d031d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -63,6 +63,26 @@ #define TU_ASSERT_COMPLETE(...) _GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_COMPLETE_2ARGS, TU_ASSERT_COMPLETE_1ARGS, _dummy)(__VA_ARGS__) +// handle line control defines +#if defined(CFG_TUH_CDC_LINE_CONTROL_ON_ENUM) && \ + (defined(CFG_TUH_CDC_DTR_CONTROL_ON_ENUM) || defined(CFG_TUH_CDC_RTS_CONTROL_ON_ENUM)) + TU_VERIFY_STATIC(false, "Contradictory line control defines"); +#endif + +#ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + #define LINE_CONTROL_ON_ENUM CFG_TUH_CDC_LINE_CONTROL_ON_ENUM +#elif defined(CFG_TUH_CDC_DTR_CONTROL_ON_ENUM) || defined(CFG_TUH_CDC_RTS_CONTROL_ON_ENUM) + #ifndef CFG_TUH_CDC_DTR_CONTROL_ON_ENUM + #define CFG_TUH_CDC_DTR_CONTROL_ON_ENUM 0 + #endif + #ifndef CFG_TUH_CDC_RTS_CONTROL_ON_ENUM + #define CFG_TUH_CDC_RTS_CONTROL_ON_ENUM 0 + #endif + #define LINE_CONTROL_ON_ENUM ( ( CFG_TUH_CDC_DTR_CONTROL_ON_ENUM ? CDC_CONTROL_LINE_STATE_DTR : 0 ) | \ + ( CFG_TUH_CDC_RTS_CONTROL_ON_ENUM ? CDC_CONTROL_LINE_STATE_RTS : 0 ) ) +#endif + + //--------------------------------------------------------------------+ // Host CDC Interface //--------------------------------------------------------------------+ @@ -1057,9 +1077,9 @@ static void acm_process_config(tuh_xfer_t * xfer) { switch (state) { case CONFIG_ACM_SET_CONTROL_LINE_STATE: - #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + #ifdef LINE_CONTROL_ON_ENUM if (p_cdc->acm_capability.support_line_request) { - p_cdc->requested_line_state.all = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(acm_set_control_line_state(p_cdc, acm_process_config, CONFIG_ACM_SET_LINE_CODING), 1); break; } @@ -1352,8 +1372,8 @@ static void ftdi_process_config(tuh_xfer_t * xfer) { break; case CONFIG_FTDI_MODEM_CTRL: - #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + #ifdef LINE_CONTROL_ON_ENUM + p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_COMPLETE)); break; #else @@ -1835,8 +1855,8 @@ static void cp210x_process_config(tuh_xfer_t * xfer) { #endif case CONFIG_CP210X_SET_DTR_RTS: - #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + #ifdef LINE_CONTROL_ON_ENUM + p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_COMPLETE)); break; @@ -2117,8 +2137,8 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { break; case CONFIG_CH34X_MODEM_CONTROL: - #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + #ifdef LINE_CONTROL_ON_ENUM + p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE)); break; @@ -2662,8 +2682,8 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { #endif case CONFIG_PL2303_MODEM_CONTROL: - #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + #ifdef LINE_CONTROL_ON_ENUM + p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; TU_ASSERT_COMPLETE(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_FLOW_CTRL_READ)); break; #else From 2786a61e8b9811b1065cf1f36502eb4744e9d772 Mon Sep 17 00:00:00 2001 From: IngHK Date: Sun, 3 Mar 2024 13:25:04 +0100 Subject: [PATCH 030/382] fixed FTDI set control line --- src/class/cdc/cdc_host.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 5b74d031d..6121e59f0 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -82,7 +82,6 @@ ( CFG_TUH_CDC_RTS_CONTROL_ON_ENUM ? CDC_CONTROL_LINE_STATE_RTS : 0 ) ) #endif - //--------------------------------------------------------------------+ // Host CDC Interface //--------------------------------------------------------------------+ @@ -1172,19 +1171,21 @@ static bool ftdi_change_speed(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_c static bool ftdi_set_data_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 7 && p_cdc->requested_line_coding.data_bits <= 8, 0); uint16_t value = (uint16_t) ( - ((uint32_t) p_cdc->requested_line_coding.data_bits & 0xf) | // data bit quantity is stored in bits 0-3 - ((uint32_t) p_cdc->requested_line_coding.parity & 0x7) << 8 | // parity is stored in bits 8-10, same coding - ((uint32_t) p_cdc->requested_line_coding.stop_bits & 0x3) << 11 ); // stop bits quantity is stored in bits 11-12, same coding - // not each FTDI supports 1.5 stop bits + ((uint32_t) p_cdc->requested_line_coding.data_bits & 0xfu) | // data bit quantity is stored in bits 0-3 + ((uint32_t) p_cdc->requested_line_coding.parity & 0x7u) << 8 | // parity is stored in bits 8-10, same coding + ((uint32_t) p_cdc->requested_line_coding.stop_bits & 0x3u) << 11 ); // stop bits quantity is stored in bits 11-12, same coding + // not each FTDI supports 1.5 stop bits return ftdi_set_request(p_cdc, FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, value, p_cdc->ftdi.channel, complete_cb, user_data); } static inline bool ftdi_update_mctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - // FTDI has the same bit coding + uint16_t value = (uint16_t) ((p_cdc->requested_line_state.dtr ? (uint32_t) FTDI_SIO_SET_DTR_HIGH : (uint32_t) FTDI_SIO_SET_DTR_LOW) | + (p_cdc->requested_line_state.rts ? (uint32_t) FTDI_SIO_SET_RTS_HIGH : (uint32_t) FTDI_SIO_SET_RTS_LOW)); + return ftdi_set_request(p_cdc, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - p_cdc->requested_line_state.all, p_cdc->ftdi.channel, complete_cb, user_data); + value, p_cdc->ftdi.channel, complete_cb, user_data); } //------------- Driver API -------------// @@ -1704,9 +1705,9 @@ static bool cp210x_set_baudrate_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t static bool cp210x_set_line_ctl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 9, 0); uint16_t lcr = (uint16_t) ( - ((uint32_t) p_cdc->requested_line_coding.data_bits & 0xf) << 8 | // data bit quantity is stored in bits 8-11 - ((uint32_t) p_cdc->requested_line_coding.parity & 0xf) << 4 | // parity is stored in bits 4-7, same coding - ((uint32_t) p_cdc->requested_line_coding.stop_bits & 0xf)); // parity is stored in bits 0-3, same coding + ((uint32_t) p_cdc->requested_line_coding.data_bits & 0xfu) << 8 | // data bit quantity is stored in bits 8-11 + ((uint32_t) p_cdc->requested_line_coding.parity & 0xfu) << 4 | // parity is stored in bits 4-7, same coding + ((uint32_t) p_cdc->requested_line_coding.stop_bits & 0xfu)); // parity is stored in bits 0-3, same coding return cp210x_set_request(p_cdc, CP210X_SET_LINE_CTL, lcr, NULL, 0, complete_cb, user_data); } From cb69ed0d0423b8e09ae77307fcc01165ae4c9386 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 21 Mar 2024 08:29:28 +0100 Subject: [PATCH 031/382] code style and clean up CDC serial header files --- src/class/cdc/serial/ch34x.h | 70 ++++++------- src/class/cdc/serial/cp210x.h | 86 ++++++++-------- src/class/cdc/serial/ftdi_sio.h | 172 ++++++++++++++++---------------- src/class/cdc/serial/pl2303.h | 120 +++++++++++----------- 4 files changed, 224 insertions(+), 224 deletions(-) diff --git a/src/class/cdc/serial/ch34x.h b/src/class/cdc/serial/ch34x.h index c18066f57..7d91f01fe 100644 --- a/src/class/cdc/serial/ch34x.h +++ b/src/class/cdc/serial/ch34x.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _CH34X_H_ -#define _CH34X_H_ +#ifndef TUSB_CH34X_H +#define TUSB_CH34X_H // There is no official documentation for the CH34x (CH340, CH341) chips. Reference can be found // - https://github.com/WCHSoftGroup/ch341ser_linux @@ -40,45 +40,45 @@ #endif // USB requests -#define CH34X_REQ_READ_VERSION 0x5F // dec 95 -#define CH34X_REQ_WRITE_REG 0x9A // dec 154 -#define CH34X_REQ_READ_REG 0x95 // dec 149 -#define CH34X_REQ_SERIAL_INIT 0xA1 // dec 161 -#define CH34X_REQ_MODEM_CTRL 0xA4 // dev 164 +#define CH34X_REQ_READ_VERSION 0x5F // dec 95 +#define CH34X_REQ_WRITE_REG 0x9A // dec 154 +#define CH34X_REQ_READ_REG 0x95 // dec 149 +#define CH34X_REQ_SERIAL_INIT 0xA1 // dec 161 +#define CH34X_REQ_MODEM_CTRL 0xA4 // dev 164 // registers -#define CH34X_REG_BREAK 0x05 -#define CH34X_REG_PRESCALER 0x12 -#define CH34X_REG_DIVISOR 0x13 -#define CH34X_REG_LCR 0x18 -#define CH34X_REG_LCR2 0x25 -#define CH34X_REG_MCR_MSR 0x06 -#define CH34X_REG_MCR_MSR2 0x07 -#define CH34X_NBREAK_BITS 0x01 +#define CH34X_REG_BREAK 0x05 +#define CH34X_REG_PRESCALER 0x12 +#define CH34X_REG_DIVISOR 0x13 +#define CH34X_REG_LCR 0x18 +#define CH34X_REG_LCR2 0x25 +#define CH34X_REG_MCR_MSR 0x06 +#define CH34X_REG_MCR_MSR2 0x07 +#define CH34X_NBREAK_BITS 0x01 -#define CH341_REG_0x0F 0x0F // undocumented register -#define CH341_REG_0x2C 0x2C // undocumented register -#define CH341_REG_0x27 0x27 // hardware flow control (cts/rts) +#define CH341_REG_0x0F 0x0F // undocumented register +#define CH341_REG_0x2C 0x2C // undocumented register +#define CH341_REG_0x27 0x27 // hardware flow control (cts/rts) -#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER) -#define CH32X_REG16_LCR2_LCR TU_U16(CH34X_REG_LCR2, CH34X_REG_LCR) +#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER) +#define CH32X_REG16_LCR2_LCR TU_U16(CH34X_REG_LCR2, CH34X_REG_LCR) // modem control bits -#define CH34X_BIT_RTS ( 1 << 6 ) -#define CH34X_BIT_DTR ( 1 << 5 ) +#define CH34X_BIT_RTS (1 << 6) +#define CH34X_BIT_DTR (1 << 5) // line control bits -#define CH34X_LCR_ENABLE_RX 0x80 -#define CH34X_LCR_ENABLE_TX 0x40 -#define CH34X_LCR_MARK_SPACE 0x20 -#define CH34X_LCR_PAR_EVEN 0x10 -#define CH34X_LCR_ENABLE_PAR 0x08 -#define CH34X_LCR_PAR_MASK 0x38 // all parity bits -#define CH34X_LCR_STOP_BITS_2 0x04 -#define CH34X_LCR_CS8 0x03 -#define CH34X_LCR_CS7 0x02 -#define CH34X_LCR_CS6 0x01 -#define CH34X_LCR_CS5 0x00 -#define CH34X_LCR_CS_MASK 0x03 // all CSx bits +#define CH34X_LCR_ENABLE_RX 0x80 +#define CH34X_LCR_ENABLE_TX 0x40 +#define CH34X_LCR_MARK_SPACE 0x20 +#define CH34X_LCR_PAR_EVEN 0x10 +#define CH34X_LCR_ENABLE_PAR 0x08 +#define CH34X_LCR_PAR_MASK 0x38 // all parity bits +#define CH34X_LCR_STOP_BITS_2 0x04 +#define CH34X_LCR_CS8 0x03 +#define CH34X_LCR_CS7 0x02 +#define CH34X_LCR_CS6 0x01 +#define CH34X_LCR_CS5 0x00 +#define CH34X_LCR_CS_MASK 0x03 // all CSx bits -#endif /* _CH34X_H_ */ +#endif // TUSB_CH34X_H diff --git a/src/class/cdc/serial/cp210x.h b/src/class/cdc/serial/cp210x.h index e18da7d51..a553a54da 100644 --- a/src/class/cdc/serial/cp210x.h +++ b/src/class/cdc/serial/cp210x.h @@ -31,7 +31,7 @@ // parts are overtaken from vendors driver // https://www.silabs.com/documents/public/software/cp210x-3.1.0.tar.gz -/* Config request codes */ +// Config request codes #define CP210X_IFC_ENABLE 0x00 #define CP210X_SET_BAUDDIV 0x01 #define CP210X_GET_BAUDDIV 0x02 @@ -60,56 +60,56 @@ #define CP210X_SET_BAUDRATE 0x1E #define CP210X_VENDOR_SPECIFIC 0xFF // GPIO, Recipient must be Device -/* SILABSER_IFC_ENABLE_REQUEST_CODE */ -#define CP210X_UART_ENABLE 0x0001 -#define CP210X_UART_DISABLE 0x0000 +// SILABSER_IFC_ENABLE_REQUEST_CODE +#define CP210X_UART_ENABLE 0x0001 +#define CP210X_UART_DISABLE 0x0000 -/* SILABSER_SET_BAUDDIV_REQUEST_CODE */ -#define CP210X_BAUD_RATE_GEN_FREQ 0x384000 +// SILABSER_SET_BAUDDIV_REQUEST_CODE +#define CP210X_BAUD_RATE_GEN_FREQ 0x384000 -/*SILABSER_SET_LINE_CTL_REQUEST_CODE */ -#define CP210X_BITS_DATA_MASK 0x0f00 -#define CP210X_BITS_DATA_5 0x0500 -#define CP210X_BITS_DATA_6 0x0600 -#define CP210X_BITS_DATA_7 0x0700 -#define CP210X_BITS_DATA_8 0x0800 -#define CP210X_BITS_DATA_9 0x0900 +// SILABSER_SET_LINE_CTL_REQUEST_CODE +#define CP210X_BITS_DATA_MASK 0x0f00 +#define CP210X_BITS_DATA_5 0x0500 +#define CP210X_BITS_DATA_6 0x0600 +#define CP210X_BITS_DATA_7 0x0700 +#define CP210X_BITS_DATA_8 0x0800 +#define CP210X_BITS_DATA_9 0x0900 -#define CP210X_BITS_PARITY_MASK 0x00f0 -#define CP210X_BITS_PARITY_NONE 0x0000 -#define CP210X_BITS_PARITY_ODD 0x0010 -#define CP210X_BITS_PARITY_EVEN 0x0020 -#define CP210X_BITS_PARITY_MARK 0x0030 -#define CP210X_BITS_PARITY_SPACE 0x0040 +#define CP210X_BITS_PARITY_MASK 0x00f0 +#define CP210X_BITS_PARITY_NONE 0x0000 +#define CP210X_BITS_PARITY_ODD 0x0010 +#define CP210X_BITS_PARITY_EVEN 0x0020 +#define CP210X_BITS_PARITY_MARK 0x0030 +#define CP210X_BITS_PARITY_SPACE 0x0040 -#define CP210X_BITS_STOP_MASK 0x000f -#define CP210X_BITS_STOP_1 0x0000 -#define CP210X_BITS_STOP_1_5 0x0001 -#define CP210X_BITS_STOP_2 0x0002 +#define CP210X_BITS_STOP_MASK 0x000f +#define CP210X_BITS_STOP_1 0x0000 +#define CP210X_BITS_STOP_1_5 0x0001 +#define CP210X_BITS_STOP_2 0x0002 -/* SILABSER_SET_BREAK_REQUEST_CODE */ -#define CP210X_BREAK_ON 0x0001 -#define CP210X_BREAK_OFF 0x0000 +// SILABSER_SET_BREAK_REQUEST_CODE +#define CP210X_BREAK_ON 0x0001 +#define CP210X_BREAK_OFF 0x0000 -/* SILABSER_SET_MHS_REQUEST_CODE */ -#define CP210X_MCR_DTR 0x0001 -#define CP210X_MCR_RTS 0x0002 -#define CP210X_MCR_ALL 0x0003 -#define CP210X_MSR_CTS 0x0010 -#define CP210X_MSR_DSR 0x0020 -#define CP210X_MSR_RING 0x0040 -#define CP210X_MSR_DCD 0x0080 -#define CP210X_MSR_ALL 0x00F0 +// SILABSER_SET_MHS_REQUEST_CODE +#define CP210X_MCR_DTR 0x0001 +#define CP210X_MCR_RTS 0x0002 +#define CP210X_MCR_ALL 0x0003 +#define CP210X_MSR_CTS 0x0010 +#define CP210X_MSR_DSR 0x0020 +#define CP210X_MSR_RING 0x0040 +#define CP210X_MSR_DCD 0x0080 +#define CP210X_MSR_ALL 0x00F0 -#define CP210X_CONTROL_WRITE_DTR 0x0100 -#define CP210X_CONTROL_WRITE_RTS 0x0200 +#define CP210X_CONTROL_WRITE_DTR 0x0100 +#define CP210X_CONTROL_WRITE_RTS 0x0200 -#define CP210X_LSR_BREAK 0x0001 -#define CP210X_LSR_FRAMING_ERROR 0x0002 -#define CP210X_LSR_HW_OVERRUN 0x0004 -#define CP210X_LSR_QUEUE_OVERRUN 0x0008 -#define CP210X_LSR_PARITY_ERROR 0x0010 -#define CP210X_LSR_ALL 0x001F +#define CP210X_LSR_BREAK 0x0001 +#define CP210X_LSR_FRAMING_ERROR 0x0002 +#define CP210X_LSR_HW_OVERRUN 0x0004 +#define CP210X_LSR_QUEUE_OVERRUN 0x0008 +#define CP210X_LSR_PARITY_ERROR 0x0010 +#define CP210X_LSR_ALL 0x001F // supported baudrates // reference: datasheets and AN205 "CP210x Baud Rate Support" diff --git a/src/class/cdc/serial/ftdi_sio.h b/src/class/cdc/serial/ftdi_sio.h index 42716f73e..4afedec9b 100644 --- a/src/class/cdc/serial/ftdi_sio.h +++ b/src/class/cdc/serial/ftdi_sio.h @@ -28,43 +28,43 @@ #include // Commands -#define FTDI_SIO_RESET 0 // Reset the port -#define FTDI_SIO_MODEM_CTRL 1 // Set the modem control register -#define FTDI_SIO_SET_FLOW_CTRL 2 // Set flow control register -#define FTDI_SIO_SET_BAUD_RATE 3 // Set baud rate -#define FTDI_SIO_SET_DATA 4 // Set the data characteristics of the port -#define FTDI_SIO_GET_MODEM_STATUS 5 // Retrieve current value of modem status register -#define FTDI_SIO_SET_EVENT_CHAR 6 // Set the event character -#define FTDI_SIO_SET_ERROR_CHAR 7 // Set the error character -#define FTDI_SIO_SET_LATENCY_TIMER 9 // Set the latency timer -#define FTDI_SIO_GET_LATENCY_TIMER 10 // Get the latency timer -#define FTDI_SIO_SET_BITMODE 11 // Set bitbang mode -#define FTDI_SIO_READ_PINS 12 // Read immediate value of pins -#define FTDI_SIO_READ_EEPROM 0x90 // Read EEPROM +#define FTDI_SIO_RESET 0 // Reset the port +#define FTDI_SIO_MODEM_CTRL 1 // Set the modem control register +#define FTDI_SIO_SET_FLOW_CTRL 2 // Set flow control register +#define FTDI_SIO_SET_BAUD_RATE 3 // Set baud rate +#define FTDI_SIO_SET_DATA 4 // Set the data characteristics of the port +#define FTDI_SIO_GET_MODEM_STATUS 5 // Retrieve current value of modem status register +#define FTDI_SIO_SET_EVENT_CHAR 6 // Set the event character +#define FTDI_SIO_SET_ERROR_CHAR 7 // Set the error character +#define FTDI_SIO_SET_LATENCY_TIMER 9 // Set the latency timer +#define FTDI_SIO_GET_LATENCY_TIMER 10 // Get the latency timer +#define FTDI_SIO_SET_BITMODE 11 // Set bitbang mode +#define FTDI_SIO_READ_PINS 12 // Read immediate value of pins +#define FTDI_SIO_READ_EEPROM 0x90 // Read EEPROM // Channel indices for FT2232, FT2232H and FT4232H devices -#define CHANNEL_A 1 -#define CHANNEL_B 2 -#define CHANNEL_C 3 -#define CHANNEL_D 4 +#define CHANNEL_A 1 +#define CHANNEL_B 2 +#define CHANNEL_C 3 +#define CHANNEL_D 4 // Port Identifier Table -#define PIT_DEFAULT 0 // SIOA -#define PIT_SIOA 1 // SIOA +#define PIT_DEFAULT 0 // SIOA +#define PIT_SIOA 1 // SIOA // The device this driver is tested with one has only one port -#define PIT_SIOB 2 // SIOB -#define PIT_PARALLEL 3 // Parallel +#define PIT_SIOB 2 // SIOB +#define PIT_PARALLEL 3 // Parallel // FTDI_SIO_RESET -#define FTDI_SIO_RESET_REQUEST FTDI_SIO_RESET -#define FTDI_SIO_RESET_REQUEST_TYPE 0x40 -#define FTDI_SIO_RESET_SIO 0 -#define FTDI_SIO_RESET_PURGE_RX 1 -#define FTDI_SIO_RESET_PURGE_TX 2 +#define FTDI_SIO_RESET_REQUEST FTDI_SIO_RESET +#define FTDI_SIO_RESET_REQUEST_TYPE 0x40 +#define FTDI_SIO_RESET_SIO 0 +#define FTDI_SIO_RESET_PURGE_RX 1 +#define FTDI_SIO_RESET_PURGE_TX 2 // FTDI_SIO_SET_BAUDRATE -#define FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE 0x40 -#define FTDI_SIO_SET_BAUDRATE_REQUEST 3 +#define FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_BAUDRATE_REQUEST 3 enum ftdi_sio_baudrate { ftdi_sio_b300 = 0, @@ -80,89 +80,89 @@ enum ftdi_sio_baudrate { }; // FTDI_SIO_SET_DATA -#define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA -#define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40 -#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8) -#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8) -#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8) -#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8) -#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8) -#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) -#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) -#define FTDI_SIO_SET_BREAK (0x1 << 14) +#define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA +#define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8) +#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8) +#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8) +#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8) +#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8) +#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) // same coding as ACM +#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) // 1.5 not supported, for future use? +#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) +#define FTDI_SIO_SET_BREAK (0x1 << 14) // FTDI_SIO_MODEM_CTRL -#define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40 -#define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL +#define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL -#define FTDI_SIO_SET_DTR_MASK 0x1 -#define FTDI_SIO_SET_DTR_HIGH ((FTDI_SIO_SET_DTR_MASK << 8) | 1) -#define FTDI_SIO_SET_DTR_LOW ((FTDI_SIO_SET_DTR_MASK << 8) | 0) -#define FTDI_SIO_SET_RTS_MASK 0x2 -#define FTDI_SIO_SET_RTS_HIGH ((FTDI_SIO_SET_RTS_MASK << 8) | 2) -#define FTDI_SIO_SET_RTS_LOW ((FTDI_SIO_SET_RTS_MASK << 8) | 0) +#define FTDI_SIO_SET_DTR_MASK 0x1 +#define FTDI_SIO_SET_DTR_HIGH ((FTDI_SIO_SET_DTR_MASK << 8) | 1) +#define FTDI_SIO_SET_DTR_LOW ((FTDI_SIO_SET_DTR_MASK << 8) | 0) +#define FTDI_SIO_SET_RTS_MASK 0x2 +#define FTDI_SIO_SET_RTS_HIGH ((FTDI_SIO_SET_RTS_MASK << 8) | 2) +#define FTDI_SIO_SET_RTS_LOW ((FTDI_SIO_SET_RTS_MASK << 8) | 0) // FTDI_SIO_SET_FLOW_CTRL -#define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40 -#define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL +#define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL #define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 -#define FTDI_SIO_RTS_CTS_HS (0x1 << 8) -#define FTDI_SIO_DTR_DSR_HS (0x2 << 8) -#define FTDI_SIO_XON_XOFF_HS (0x4 << 8) +#define FTDI_SIO_RTS_CTS_HS (0x1 << 8) +#define FTDI_SIO_DTR_DSR_HS (0x2 << 8) +#define FTDI_SIO_XON_XOFF_HS (0x4 << 8) // FTDI_SIO_GET_LATENCY_TIMER -#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST FTDI_SIO_GET_LATENCY_TIMER -#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE 0xC0 +#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST FTDI_SIO_GET_LATENCY_TIMER +#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE 0xC0 // FTDI_SIO_SET_LATENCY_TIMER -#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER -#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER +#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40 // FTDI_SIO_SET_EVENT_CHAR -#define FTDI_SIO_SET_EVENT_CHAR_REQUEST FTDI_SIO_SET_EVENT_CHAR -#define FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_EVENT_CHAR_REQUEST FTDI_SIO_SET_EVENT_CHAR +#define FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40 // FTDI_SIO_GET_MODEM_STATUS -#define FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE 0xc0 -#define FTDI_SIO_GET_MODEM_STATUS_REQUEST FTDI_SIO_GET_MODEM_STATUS -#define FTDI_SIO_CTS_MASK 0x10 -#define FTDI_SIO_DSR_MASK 0x20 -#define FTDI_SIO_RI_MASK 0x40 -#define FTDI_SIO_RLSD_MASK 0x80 +#define FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE 0xc0 +#define FTDI_SIO_GET_MODEM_STATUS_REQUEST FTDI_SIO_GET_MODEM_STATUS +#define FTDI_SIO_CTS_MASK 0x10 +#define FTDI_SIO_DSR_MASK 0x20 +#define FTDI_SIO_RI_MASK 0x40 +#define FTDI_SIO_RLSD_MASK 0x80 // FTDI_SIO_SET_BITMODE -#define FTDI_SIO_SET_BITMODE_REQUEST_TYPE 0x40 -#define FTDI_SIO_SET_BITMODE_REQUEST FTDI_SIO_SET_BITMODE +#define FTDI_SIO_SET_BITMODE_REQUEST_TYPE 0x40 +#define FTDI_SIO_SET_BITMODE_REQUEST FTDI_SIO_SET_BITMODE // Possible bitmodes for FTDI_SIO_SET_BITMODE_REQUEST -#define FTDI_SIO_BITMODE_RESET 0x00 -#define FTDI_SIO_BITMODE_CBUS 0x20 +#define FTDI_SIO_BITMODE_RESET 0x00 +#define FTDI_SIO_BITMODE_CBUS 0x20 // FTDI_SIO_READ_PINS -#define FTDI_SIO_READ_PINS_REQUEST_TYPE 0xc0 -#define FTDI_SIO_READ_PINS_REQUEST FTDI_SIO_READ_PINS +#define FTDI_SIO_READ_PINS_REQUEST_TYPE 0xc0 +#define FTDI_SIO_READ_PINS_REQUEST FTDI_SIO_READ_PINS // FTDI_SIO_READ_EEPROM -#define FTDI_SIO_READ_EEPROM_REQUEST_TYPE 0xc0 -#define FTDI_SIO_READ_EEPROM_REQUEST FTDI_SIO_READ_EEPROM +#define FTDI_SIO_READ_EEPROM_REQUEST_TYPE 0xc0 +#define FTDI_SIO_READ_EEPROM_REQUEST FTDI_SIO_READ_EEPROM #define FTDI_FTX_CBUS_MUX_GPIO 0x8 #define FTDI_FT232R_CBUS_MUX_GPIO 0xa #define FTDI_RS0_CTS (1 << 4) #define FTDI_RS0_DSR (1 << 5) -#define FTDI_RS0_RI (1 << 6) +#define FTDI_RS0_RI (1 << 6) #define FTDI_RS0_RLSD (1 << 7) -#define FTDI_RS_DR 1 -#define FTDI_RS_OE (1<<1) -#define FTDI_RS_PE (1<<2) -#define FTDI_RS_FE (1<<3) -#define FTDI_RS_BI (1<<4) -#define FTDI_RS_THRE (1<<5) -#define FTDI_RS_TEMT (1<<6) -#define FTDI_RS_FIFO (1<<7) +#define FTDI_RS_DR 1 +#define FTDI_RS_OE (1 << 1) +#define FTDI_RS_PE (1 << 2) +#define FTDI_RS_FE (1 << 3) +#define FTDI_RS_BI (1 << 4) +#define FTDI_RS_THRE (1 << 5) +#define FTDI_RS_TEMT (1 << 6) +#define FTDI_RS_FIFO (1 << 7) // chip types and names enum ftdi_chip_type { @@ -206,14 +206,14 @@ enum ftdi_chip_type { // private interface data typedef struct ftdi_private { - enum ftdi_chip_type chip_type; - uint8_t channel; // channel index, or 0 for legacy types + enum ftdi_chip_type chip_type; + uint8_t channel; // channel index, or 0 for legacy types } ftdi_private_t; -#define FTDI_OK true -#define FTDI_FAIL false +#define FTDI_OK true +#define FTDI_FAIL false #define FTDI_NOT_POSSIBLE -1 -#define FTDI_REQUESTED -2 +#define FTDI_REQUESTED -2 // division and round function overtaken from math.h #define DIV_ROUND_CLOSEST(x, divisor)( \ diff --git a/src/class/cdc/serial/pl2303.h b/src/class/cdc/serial/pl2303.h index bf264191b..d69bdbfae 100644 --- a/src/class/cdc/serial/pl2303.h +++ b/src/class/cdc/serial/pl2303.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _PL2303_H_ -#define _PL2303_H_ +#ifndef TUSB_PL2303_H +#define TUSB_PL2303_H #include #include @@ -36,66 +36,66 @@ // https://github.com/torvalds/linux/blob/master/drivers/usb/serial/pl2303.c // - https://github.com/freebsd/freebsd-src/blob/main/sys/dev/usb/serial/uplcom.c -/* quirks */ -#define PL2303_QUIRK_UART_STATE_IDX0 1 -#define PL2303_QUIRK_LEGACY 2 -#define PL2303_QUIRK_ENDPOINT_HACK 4 +// quirks +#define PL2303_QUIRK_UART_STATE_IDX0 1 +#define PL2303_QUIRK_LEGACY 2 +#define PL2303_QUIRK_ENDPOINT_HACK 4 -/* requests and bits */ -#define PL2303_SET_LINE_REQUEST_TYPE 0x21 // class request host to device interface -#define PL2303_SET_LINE_REQUEST 0x20 // dec 32 +// requests and bits +#define PL2303_SET_LINE_REQUEST_TYPE 0x21 // class request host to device interface +#define PL2303_SET_LINE_REQUEST 0x20 // dec 32 -#define PL2303_SET_CONTROL_REQUEST_TYPE 0x21 // class request host to device interface -#define PL2303_SET_CONTROL_REQUEST 0x22 // dec 34 -#define PL2303_CONTROL_DTR 0x01 // dec 1 -#define PL2303_CONTROL_RTS 0x02 // dec 2 +#define PL2303_SET_CONTROL_REQUEST_TYPE 0x21 // class request host to device interface +#define PL2303_SET_CONTROL_REQUEST 0x22 // dec 34 +#define PL2303_CONTROL_DTR 0x01 // dec 1 +#define PL2303_CONTROL_RTS 0x02 // dec 2 -#define PL2303_BREAK_REQUEST_TYPE 0x21 // class request host to device interface -#define PL2303_BREAK_REQUEST 0x23 // dec 35 -#define PL2303_BREAK_ON 0xffff -#define PL2303_BREAK_OFF 0x0000 +#define PL2303_BREAK_REQUEST_TYPE 0x21 // class request host to device interface +#define PL2303_BREAK_REQUEST 0x23 // dec 35 +#define PL2303_BREAK_ON 0xffff +#define PL2303_BREAK_OFF 0x0000 -#define PL2303_GET_LINE_REQUEST_TYPE 0xa1 // class request device to host interface -#define PL2303_GET_LINE_REQUEST 0x21 // dec 33 +#define PL2303_GET_LINE_REQUEST_TYPE 0xa1 // class request device to host interface +#define PL2303_GET_LINE_REQUEST 0x21 // dec 33 -#define PL2303_VENDOR_WRITE_REQUEST_TYPE 0x40 // vendor request host to device interface -#define PL2303_VENDOR_WRITE_REQUEST 0x01 // dec 1 -#define PL2303_VENDOR_WRITE_NREQUEST 0x80 // dec 128 +#define PL2303_VENDOR_WRITE_REQUEST_TYPE 0x40 // vendor request host to device interface +#define PL2303_VENDOR_WRITE_REQUEST 0x01 // dec 1 +#define PL2303_VENDOR_WRITE_NREQUEST 0x80 // dec 128 -#define PL2303_VENDOR_READ_REQUEST_TYPE 0xc0 // vendor request device to host interface -#define PL2303_VENDOR_READ_REQUEST 0x01 // dec 1 -#define PL2303_VENDOR_READ_NREQUEST 0x81 // dec 129 +#define PL2303_VENDOR_READ_REQUEST_TYPE 0xc0 // vendor request device to host interface +#define PL2303_VENDOR_READ_REQUEST 0x01 // dec 1 +#define PL2303_VENDOR_READ_NREQUEST 0x81 // dec 129 -#define PL2303_UART_STATE_INDEX 8 -#define PL2303_UART_STATE_MSR_MASK 0x8b -#define PL2303_UART_STATE_TRANSIENT_MASK 0x74 -#define PL2303_UART_DCD 0x01 -#define PL2303_UART_DSR 0x02 -#define PL2303_UART_BREAK_ERROR 0x04 -#define PL2303_UART_RING 0x08 -#define PL2303_UART_FRAME_ERROR 0x10 -#define PL2303_UART_PARITY_ERROR 0x20 -#define PL2303_UART_OVERRUN_ERROR 0x40 -#define PL2303_UART_CTS 0x80 +#define PL2303_UART_STATE_INDEX 8 +#define PL2303_UART_STATE_MSR_MASK 0x8b +#define PL2303_UART_STATE_TRANSIENT_MASK 0x74 +#define PL2303_UART_DCD 0x01 +#define PL2303_UART_DSR 0x02 +#define PL2303_UART_BREAK_ERROR 0x04 +#define PL2303_UART_RING 0x08 +#define PL2303_UART_FRAME_ERROR 0x10 +#define PL2303_UART_PARITY_ERROR 0x20 +#define PL2303_UART_OVERRUN_ERROR 0x40 +#define PL2303_UART_CTS 0x80 -#define PL2303_FLOWCTRL_MASK 0xf0 +#define PL2303_FLOWCTRL_MASK 0xf0 -#define PL2303_CLEAR_HALT_REQUEST_TYPE 0x02 // standard request host to device endpoint +#define PL2303_CLEAR_HALT_REQUEST_TYPE 0x02 // standard request host to device endpoint -/* registers via vendor read/write requests */ -#define PL2303_READ_TYPE_HX_STATUS 0x8080 +// registers via vendor read/write requests +#define PL2303_READ_TYPE_HX_STATUS 0x8080 -#define PL2303_HXN_RESET_REG 0x07 -#define PL2303_HXN_RESET_UPSTREAM_PIPE 0x02 -#define PL2303_HXN_RESET_DOWNSTREAM_PIPE 0x01 +#define PL2303_HXN_RESET_REG 0x07 +#define PL2303_HXN_RESET_UPSTREAM_PIPE 0x02 +#define PL2303_HXN_RESET_DOWNSTREAM_PIPE 0x01 -#define PL2303_HXN_FLOWCTRL_REG 0x0a -#define PL2303_HXN_FLOWCTRL_MASK 0x1c -#define PL2303_HXN_FLOWCTRL_NONE 0x1c -#define PL2303_HXN_FLOWCTRL_RTS_CTS 0x18 -#define PL2303_HXN_FLOWCTRL_XON_XOFF 0x0c +#define PL2303_HXN_FLOWCTRL_REG 0x0a +#define PL2303_HXN_FLOWCTRL_MASK 0x1c +#define PL2303_HXN_FLOWCTRL_NONE 0x1c +#define PL2303_HXN_FLOWCTRL_RTS_CTS 0x18 +#define PL2303_HXN_FLOWCTRL_XON_XOFF 0x0c -/* type data */ +// type data enum pl2303_type { TYPE_H, TYPE_HX, @@ -107,9 +107,9 @@ enum pl2303_type { }; struct pl2303_type_data { - uint8_t const *name; + uint8_t const *name; uint32_t const max_baud_rate; - uint8_t const quirks; + uint8_t const quirks; uint16_t const no_autoxonxoff:1; uint16_t const no_divisors:1; uint16_t const alt_divisors:1; @@ -146,7 +146,7 @@ struct pl2303_type_data { .no_divisors = true, \ } -/* private data types */ +// private data types struct pl2303_serial_private { const struct pl2303_type_data* type; uint8_t quirks; @@ -157,16 +157,16 @@ typedef struct TU_ATTR_PACKED { bool supports_hx_status; } pl2303_private_t; -/* buffer sizes for line coding data */ -#define PL2303_LINE_CODING_BUFSIZE 7 +// buffer sizes for line coding data +#define PL2303_LINE_CODING_BUFSIZE 7 #define PL2303_LINE_CODING_BAUDRATE_BUFSIZE 4 -/* bulk endpoints */ -#define PL2303_OUT_EP 0x02 -#define PL2303_IN_EP 0x83 +// bulk endpoints +#define PL2303_OUT_EP 0x02 +#define PL2303_IN_EP 0x83 -/* return values of pl2303_detect_type() */ +// return values of pl2303_detect_type() #define PL2303_SUPPORTS_HX_STATUS_TRIGGERED -1 -#define PL2303_DETECT_TYPE_FAILED -2 +#define PL2303_DETECT_TYPE_FAILED -2 -#endif /* _PL2303_H_ */ +#endif // TUSB_PL2303_H From 5e67b92b8c398d6fee92010ecd63cf50b51f8f9a Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 4 Apr 2024 14:10:31 +0200 Subject: [PATCH 032/382] fixed compile warnings --- src/class/cdc/cdc_host.c | 29 ++++++++++++++++------------- src/class/cdc/serial/cp210x.h | 4 ++-- src/class/cdc/serial/ftdi_sio.h | 14 +++++++------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index e6579ad82..2d900a753 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -1181,9 +1181,9 @@ static bool ftdi_change_speed(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_c static bool ftdi_set_data_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 7 && p_cdc->requested_line_coding.data_bits <= 8, 0); uint16_t value = (uint16_t) ( - ((uint32_t) p_cdc->requested_line_coding.data_bits & 0xfu) | // data bit quantity is stored in bits 0-3 - ((uint32_t) p_cdc->requested_line_coding.parity & 0x7u) << 8 | // parity is stored in bits 8-10, same coding - ((uint32_t) p_cdc->requested_line_coding.stop_bits & 0x3u) << 11 ); // stop bits quantity is stored in bits 11-12, same coding + (p_cdc->requested_line_coding.data_bits & 0xfUL) | // data bit quantity is stored in bits 0-3 + (p_cdc->requested_line_coding.parity & 0x7UL) << 8 | // parity is stored in bits 8-10, same coding + (p_cdc->requested_line_coding.stop_bits & 0x3UL) << 11 ); // stop bits quantity is stored in bits 11-12, same coding // not each FTDI supports 1.5 stop bits return ftdi_set_request(p_cdc, FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, @@ -1191,8 +1191,8 @@ static bool ftdi_set_data_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t comple } static inline bool ftdi_update_mctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint16_t value = (uint16_t) ((p_cdc->requested_line_state.dtr ? (uint32_t) FTDI_SIO_SET_DTR_HIGH : (uint32_t) FTDI_SIO_SET_DTR_LOW) | - (p_cdc->requested_line_state.rts ? (uint32_t) FTDI_SIO_SET_RTS_HIGH : (uint32_t) FTDI_SIO_SET_RTS_LOW)); + uint16_t value = (uint16_t) ((p_cdc->requested_line_state.dtr ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW) | + (p_cdc->requested_line_state.rts ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW)); return ftdi_set_request(p_cdc, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, value, p_cdc->ftdi.channel, complete_cb, user_data); @@ -1338,7 +1338,10 @@ static void ftdi_process_config(tuh_xfer_t * xfer) { // other interfaces have same type as interface 0 uint8_t const idx_itf0 = tuh_cdc_itf_get_index(xfer->daddr, 0); cdch_interface_t const * p_cdc_itf0 = get_itf(idx_itf0); - p_cdc->ftdi.chip_type = p_cdc_itf0->ftdi.chip_type; + TU_ASSERT_COMPLETE(p_cdc_itf0); + if (p_cdc_itf0) { + p_cdc->ftdi.chip_type = p_cdc_itf0->ftdi.chip_type; + } } TU_ATTR_FALLTHROUGH; @@ -1715,9 +1718,9 @@ static bool cp210x_set_baudrate_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t static bool cp210x_set_line_ctl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 9, 0); uint16_t lcr = (uint16_t) ( - ((uint32_t) p_cdc->requested_line_coding.data_bits & 0xfu) << 8 | // data bit quantity is stored in bits 8-11 - ((uint32_t) p_cdc->requested_line_coding.parity & 0xfu) << 4 | // parity is stored in bits 4-7, same coding - ((uint32_t) p_cdc->requested_line_coding.stop_bits & 0xfu)); // parity is stored in bits 0-3, same coding + (p_cdc->requested_line_coding.data_bits & 0xfUL) << 8 | // data bit quantity is stored in bits 8-11 + (p_cdc->requested_line_coding.parity & 0xfUL) << 4 | // parity is stored in bits 4-7, same coding + (p_cdc->requested_line_coding.stop_bits & 0xfUL)); // parity is stored in bits 0-3, same coding return cp210x_set_request(p_cdc, CP210X_SET_LINE_CTL, lcr, NULL, 0, complete_cb, user_data); } @@ -1725,8 +1728,8 @@ static bool cp210x_set_line_ctl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete static inline bool cp210x_set_mhs(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // CP210x has the same bit coding return cp210x_set_request(p_cdc, CP210X_SET_MHS, - (uint16_t) ((uint32_t) CP210X_CONTROL_WRITE_DTR | - (uint32_t) CP210X_CONTROL_WRITE_RTS | p_cdc->requested_line_state.all), + (uint16_t) (CP210X_CONTROL_WRITE_DTR | CP210X_CONTROL_WRITE_RTS | + p_cdc->requested_line_state.all), NULL, 0, complete_cb, user_data); } @@ -2327,7 +2330,7 @@ static bool pl2303_vendor_write(cdch_interface_t * p_cdc, uint16_t value, uint16 static inline bool pl2303_supports_hx_status(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t buf; + uint8_t buf = 0; return pl2303_set_request(p_cdc, PL2303_VENDOR_READ_REQUEST, PL2303_VENDOR_READ_REQUEST_TYPE, PL2303_READ_TYPE_HX_STATUS, 0, &buf, 1, complete_cb, user_data); @@ -2519,7 +2522,7 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { cdch_interface_t * p_cdc = get_itf(idx); // state CONFIG_PL2303_READ1 may have no success due to expected stall by pl2303_supports_hx_status() TU_ASSERT_COMPLETE(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || xfer->user_data == CONFIG_PL2303_READ1)); - uint8_t buf; + uint8_t buf = 0; int8_t type; switch (state) { diff --git a/src/class/cdc/serial/cp210x.h b/src/class/cdc/serial/cp210x.h index a553a54da..ac9c27330 100644 --- a/src/class/cdc/serial/cp210x.h +++ b/src/class/cdc/serial/cp210x.h @@ -101,8 +101,8 @@ #define CP210X_MSR_DCD 0x0080 #define CP210X_MSR_ALL 0x00F0 -#define CP210X_CONTROL_WRITE_DTR 0x0100 -#define CP210X_CONTROL_WRITE_RTS 0x0200 +#define CP210X_CONTROL_WRITE_DTR 0x0100UL +#define CP210X_CONTROL_WRITE_RTS 0x0200UL #define CP210X_LSR_BREAK 0x0001 #define CP210X_LSR_FRAMING_ERROR 0x0002 diff --git a/src/class/cdc/serial/ftdi_sio.h b/src/class/cdc/serial/ftdi_sio.h index 4afedec9b..f621b3912 100644 --- a/src/class/cdc/serial/ftdi_sio.h +++ b/src/class/cdc/serial/ftdi_sio.h @@ -96,17 +96,17 @@ enum ftdi_sio_baudrate { #define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40 #define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL -#define FTDI_SIO_SET_DTR_MASK 0x1 -#define FTDI_SIO_SET_DTR_HIGH ((FTDI_SIO_SET_DTR_MASK << 8) | 1) -#define FTDI_SIO_SET_DTR_LOW ((FTDI_SIO_SET_DTR_MASK << 8) | 0) -#define FTDI_SIO_SET_RTS_MASK 0x2 -#define FTDI_SIO_SET_RTS_HIGH ((FTDI_SIO_SET_RTS_MASK << 8) | 2) -#define FTDI_SIO_SET_RTS_LOW ((FTDI_SIO_SET_RTS_MASK << 8) | 0) +#define FTDI_SIO_SET_DTR_MASK 0x1UL +#define FTDI_SIO_SET_DTR_HIGH ((FTDI_SIO_SET_DTR_MASK << 8) | 1UL) +#define FTDI_SIO_SET_DTR_LOW ((FTDI_SIO_SET_DTR_MASK << 8) | 0UL) +#define FTDI_SIO_SET_RTS_MASK 0x2UL +#define FTDI_SIO_SET_RTS_HIGH ((FTDI_SIO_SET_RTS_MASK << 8) | 2UL) +#define FTDI_SIO_SET_RTS_LOW ((FTDI_SIO_SET_RTS_MASK << 8) | 0UL) // FTDI_SIO_SET_FLOW_CTRL #define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40 #define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL -#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 +#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 #define FTDI_SIO_RTS_CTS_HS (0x1 << 8) #define FTDI_SIO_DTR_DSR_HS (0x2 << 8) #define FTDI_SIO_XON_XOFF_HS (0x4 << 8) From e07ee4a7b1f7c7d18f385d605dd41e08962ddba4 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 4 Apr 2024 14:12:14 +0200 Subject: [PATCH 033/382] CP210x removed baudrate check, fixed data bits check --- src/class/cdc/cdc_host.c | 12 ++---------- src/class/cdc/serial/cp210x.h | 9 --------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 2d900a753..73d800469 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -1701,22 +1701,14 @@ static inline bool cp210x_ifc_enable(cdch_interface_t * p_cdc, uint16_t enabled, } static bool cp210x_set_baudrate_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - // Check baudrate is supported. It's only a specific list. reference: datasheets and AN205 "CP210x Baud Rate Support" - uint32_t const supported_baudrates_list[] = CP210X_SUPPORTED_BAUDRATES_LIST; - uint8_t i; - for ( i=0; supported_baudrates_list[i]; i++ ){ - if (p_cdc->requested_line_coding.bit_rate == supported_baudrates_list[i]) { - break; - } - } - TU_VERIFY(supported_baudrates_list[i]); + // Not every baud rate is supported. See datasheets and AN205 "CP210x Baud Rate Support" uint32_t baud_le = tu_htole32(p_cdc->requested_line_coding.bit_rate); return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, complete_cb, user_data); } static bool cp210x_set_line_ctl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 9, 0); + TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8, 0); uint16_t lcr = (uint16_t) ( (p_cdc->requested_line_coding.data_bits & 0xfUL) << 8 | // data bit quantity is stored in bits 8-11 (p_cdc->requested_line_coding.parity & 0xfUL) << 4 | // parity is stored in bits 4-7, same coding diff --git a/src/class/cdc/serial/cp210x.h b/src/class/cdc/serial/cp210x.h index ac9c27330..a0eff9e40 100644 --- a/src/class/cdc/serial/cp210x.h +++ b/src/class/cdc/serial/cp210x.h @@ -111,13 +111,4 @@ #define CP210X_LSR_PARITY_ERROR 0x0010 #define CP210X_LSR_ALL 0x001F -// supported baudrates -// reference: datasheets and AN205 "CP210x Baud Rate Support" -#define CP210X_SUPPORTED_BAUDRATES_LIST { \ - 300, 600, \ - 1200, 1800, 2400, 4000, 4800, 7200, 9600, \ - 14400, 16000, 19200, 28800, 38400, 51200, 56000, 57600, 64000, 76800, \ - 115200, 128000, 153600, 230400, 250000, 256000, 460800, 500000, 576000, 921600, \ - 0 } - #endif //TUSB_CP210X_H From a1b1c1f552d944da1bf309ce002b7c07f5a270a0 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 4 Apr 2024 14:13:24 +0200 Subject: [PATCH 034/382] foxed FTDI flow control config --- src/class/cdc/cdc_host.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 73d800469..6006730b7 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -1382,7 +1382,8 @@ static void ftdi_process_config(tuh_xfer_t * xfer) { case CONFIG_FTDI_FLOW_CONTROL: // disable flow control TU_ASSERT_COMPLETE(ftdi_set_request(p_cdc, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, FTDI_SIO_DISABLE_FLOW_CTRL, ftdi_process_config, CONFIG_FTDI_MODEM_CTRL)); + FTDI_SIO_DISABLE_FLOW_CTRL, p_cdc->ftdi.channel, + ftdi_process_config, CONFIG_FTDI_MODEM_CTRL)); break; case CONFIG_FTDI_MODEM_CTRL: From e02a309f1dc09377fe5123c21ecfe36eb6a032c7 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 4 Apr 2024 14:14:41 +0200 Subject: [PATCH 035/382] disable PL2303 flow control config --- src/class/cdc/cdc_host.c | 55 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 6006730b7..b9915f583 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -2475,8 +2475,8 @@ enum { CONFIG_PL2303_RESET_ENDP2, CONFIG_PL2303_LINE_CODING, CONFIG_PL2303_MODEM_CONTROL, - CONFIG_PL2303_FLOW_CTRL_READ, - CONFIG_PL2303_FLOW_CTRL_WRITE, +// CONFIG_PL2303_FLOW_CTRL_READ, +// CONFIG_PL2303_FLOW_CTRL_WRITE, CONFIG_PL2303_COMPLETE }; @@ -2691,35 +2691,38 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { case CONFIG_PL2303_MODEM_CONTROL: #ifdef LINE_CONTROL_ON_ENUM p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; - TU_ASSERT_COMPLETE(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_FLOW_CTRL_READ)); + TU_ASSERT_COMPLETE(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; #endif - case CONFIG_PL2303_FLOW_CTRL_READ: - // read flow control register for modify & write back in next step - if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, PL2303_HXN_FLOWCTRL_REG, &buf, pl2303_process_config, - CONFIG_PL2303_FLOW_CTRL_WRITE)); - } else { - TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0, &buf, pl2303_process_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); - } - break; - - case CONFIG_PL2303_FLOW_CTRL_WRITE: - // no flow control - buf = xfer->buffer[0]; - if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { - buf &= (uint8_t) ~PL2303_HXN_FLOWCTRL_MASK; - buf |= PL2303_HXN_FLOWCTRL_NONE; - TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, PL2303_HXN_FLOWCTRL_REG, buf, pl2303_process_config, - CONFIG_PL2303_COMPLETE)); - } else { - buf &= (uint8_t) ~PL2303_FLOWCTRL_MASK; - TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 0, buf, pl2303_process_config, CONFIG_PL2303_COMPLETE)); - } - break; +// skipped, because it's not working with each PL230x. flow control can be also set by PL2303 EEPROM Writer Program +// case CONFIG_PL2303_FLOW_CTRL_READ: +// // read flow control register for modify & write back in next step +// if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { +// TU_LOG_P_CDC ( "1\r\n" ); +// TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, PL2303_HXN_FLOWCTRL_REG, &buf, pl2303_process_config, +// CONFIG_PL2303_FLOW_CTRL_WRITE)); +// } else { +// TU_LOG_P_CDC ( "2\r\n" ); +// TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0, &buf, pl2303_process_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); +// } +// break; +// +// case CONFIG_PL2303_FLOW_CTRL_WRITE: +// // no flow control +// buf = xfer->buffer[0]; +// if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { +// buf &= (uint8_t) ~PL2303_HXN_FLOWCTRL_MASK; +// buf |= PL2303_HXN_FLOWCTRL_NONE; +// TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, PL2303_HXN_FLOWCTRL_REG, buf, pl2303_process_config, +// CONFIG_PL2303_COMPLETE)); +// } else { +// buf &= (uint8_t) ~PL2303_FLOWCTRL_MASK; +// TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 0, buf, pl2303_process_config, CONFIG_PL2303_COMPLETE)); +// } +// break; case CONFIG_PL2303_COMPLETE: set_config_complete(idx, 0, true); From 68602e4adda941ab11826afbd7b82e44134a97ae Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 4 Apr 2024 14:16:02 +0200 Subject: [PATCH 036/382] small change process config complete --- src/class/cdc/cdc_host.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index b9915f583..fbe0cc9ca 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -1400,7 +1400,7 @@ static void ftdi_process_config(tuh_xfer_t * xfer) { break; default: - set_config_complete(idx, 0, false); + TU_ASSERT_COMPLETE(false); break; } } @@ -1876,7 +1876,7 @@ static void cp210x_process_config(tuh_xfer_t * xfer) { break; default: - set_config_complete(idx, 0, false); + TU_ASSERT_COMPLETE(false); break; } } @@ -2158,7 +2158,7 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { break; default: - set_config_complete(idx, 0, false); + TU_ASSERT_COMPLETE(false); break; } } @@ -2729,7 +2729,7 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { break; default: - set_config_complete(idx, 0, false); + TU_ASSERT_COMPLETE(false); break; } } From 0c5e14cdaa98b3d801fcaf05e3b6c941031a55b2 Mon Sep 17 00:00:00 2001 From: IngHK Date: Thu, 4 Apr 2024 14:16:39 +0200 Subject: [PATCH 037/382] updated doc --- docs/reference/index.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/reference/index.rst b/docs/reference/index.rst index 9ecdf619b..509babef2 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -27,7 +27,7 @@ Supports multiple device configurations by dynamically changing USB descriptors, - Audio Class 2.0 (UAC2) - Bluetooth Host Controller Interface (BTH HCI) -- Communication Device Class (CDC) +- Communications Device Class (CDC) - Device Firmware Update (DFU): DFU mode (WIP) and Runtime - Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ... - Mass Storage Class (MSC): with multiple LUNs @@ -45,8 +45,8 @@ Host Stack - Human Interface Device (HID): Keyboard, Mouse, Generic - Mass Storage Class (MSC) -- Communication Device Class: CDC-ACM -- Vendor serial over USB: FTDI, CP210x +- Communications Device Class (CDC): Abstract Control Model (ACM) +- Vendor serial over USB: FTDI, CP210x, CH34x, PL230x - Hub with multiple-level support Similar to the Device Stack, if you have a special requirement, `usbh_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. From 8b4ca69e56860e12596e2bef63fc155f8dce338c Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Apr 2024 01:14:30 +0200 Subject: [PATCH 038/382] cdc_device : save rhport. --- src/class/cdc/cdc_device.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 2e0a0c30d..e856963f5 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -47,6 +47,7 @@ typedef struct { + uint8_t rhport; uint8_t itf_num; uint8_t ep_notif; uint8_t ep_in; @@ -84,7 +85,6 @@ CFG_TUD_MEM_SECTION tu_static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; static bool _prep_out_transaction (cdcd_interface_t* p_cdc) { - uint8_t const rhport = 0; uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); // Prepare for incoming data but only allow what we can store in the ring buffer. @@ -94,18 +94,18 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) TU_VERIFY(available >= sizeof(p_cdc->epout_buf)); // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out)); + TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_out)); // fifo can be changed before endpoint is claimed available = tu_fifo_remaining(&p_cdc->rx_ff); if ( available >= sizeof(p_cdc->epout_buf) ) { - return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); + return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf)); }else { // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_cdc->ep_out); + usbd_edpt_release(p_cdc->rhport, p_cdc->ep_out); return false; } @@ -135,7 +135,6 @@ void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted) _cdcd_itf[itf].wanted_char = wanted; } - //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ @@ -194,23 +193,21 @@ uint32_t tud_cdc_n_write_flush (uint8_t itf) // No data to send if ( !tu_fifo_count(&p_cdc->tx_ff) ) return 0; - uint8_t const rhport = 0; - // Claim the endpoint - TU_VERIFY( usbd_edpt_claim(rhport, p_cdc->ep_in), 0 ); + TU_VERIFY( usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_in), 0 ); // Pull data from FIFO uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf)); if ( count ) { - TU_ASSERT( usbd_edpt_xfer(rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); + TU_ASSERT( usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_in, p_cdc->epin_buf, count), 0 ); return count; }else { // Release endpoint since we don't make any transfer // Note: data is dropped if terminal is not connected - usbd_edpt_release(rhport, p_cdc->ep_in); + usbd_edpt_release(p_cdc->rhport, p_cdc->ep_in); return 0; } } @@ -319,6 +316,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 TU_ASSERT(p_cdc, 0); //------------- Control Interface -------------// + p_cdc->rhport = rhport; p_cdc->itf_num = itf_desc->bInterfaceNumber; uint16_t drv_len = sizeof(tusb_desc_interface_t); From 67f32da1b9a460262e028784ffb0386edd507612 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Apr 2024 01:15:46 +0200 Subject: [PATCH 039/382] cdc: add uart status notification support. --- src/class/cdc/cdc.h | 29 +++++++++++++++++++++++++++++ src/class/cdc/cdc_device.c | 24 +++++++++++++++++++++++- src/class/cdc/cdc_device.h | 9 +++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 5cbd658fe..f92ab9231 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -412,6 +412,35 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct"); +//--------------------------------------------------------------------+ +// Notifications +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED +{ + uint16_t bRxCarrier : 1; + uint16_t bTxCarrier : 1; + uint16_t bBreak : 1; + uint16_t bRingSignal : 1; + uint16_t bFraming : 1; + uint16_t bParity : 1; + uint16_t bOverRun : 1; + uint16_t : 9; +} cdc_uart_state_t; + +typedef struct TU_ATTR_PACKED +{ + uint8_t bmRequestType; + uint8_t bNotification; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + cdc_uart_state_t bmUartState; +} cdc_notif_serial_state_t; + +TU_VERIFY_STATIC(sizeof(cdc_notif_serial_state_t) == 10, "size is not correct"); + +#define CDC_REQ_TYPE_NOTIF 0xA1 ///< Direction IN; Type Class; Recipient Interface + TU_ATTR_PACKED_END // End of all packed definitions TU_ATTR_BIT_FIELD_ORDER_END diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index e856963f5..5057805e2 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -71,6 +71,7 @@ typedef struct OSAL_MUTEX_DEF(tx_ff_mutex); // Endpoint Transfer buffer + CFG_TUSB_MEM_ALIGN cdc_notif_serial_state_t serial_state_buf; CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE]; @@ -130,6 +131,27 @@ void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding) (*coding) = _cdcd_itf[itf].line_coding; } +bool tud_cdc_n_send_uart_state (uint8_t itf, cdc_uart_state_t state) +{ + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + + // Skip if usb is not ready yet + TU_VERIFY( tud_ready(), 0 ); + + // claim endpoint + TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notif)); + + p_cdc->serial_state_buf.bmRequestType = CDC_REQ_TYPE_NOTIF; + p_cdc->serial_state_buf.bNotification = CDC_NOTIF_SERIAL_STATE; + p_cdc->serial_state_buf.wValue = 0; + p_cdc->serial_state_buf.wIndex = p_cdc->itf_num; + p_cdc->serial_state_buf.wLength = 2; + p_cdc->serial_state_buf.bmUartState = state; + + // transfer + return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notif, (uint8_t *)&p_cdc->serial_state_buf, sizeof(p_cdc->serial_state_buf)); +} + void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted) { _cdcd_itf[itf].wanted_char = wanted; @@ -457,7 +479,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ for (itf = 0; itf < CFG_TUD_CDC; itf++) { p_cdc = &_cdcd_itf[itf]; - if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) ) break; + if ( ( ep_addr == p_cdc->ep_out ) || ( ep_addr == p_cdc->ep_in ) || ( ep_addr == p_cdc->ep_notif )) break; } TU_ASSERT(itf < CFG_TUD_CDC); diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 20e908451..92131f159 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -64,6 +64,9 @@ uint8_t tud_cdc_n_get_line_state (uint8_t itf); // Get current line encoding: bit rate, stop bits parity etc .. void tud_cdc_n_get_line_coding (uint8_t itf, cdc_line_coding_t* coding); +// Send UART status notification: DCD, DSR etc .. +bool tud_cdc_n_send_uart_state (uint8_t itf, cdc_uart_state_t state); + // Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving void tud_cdc_n_set_wanted_char (uint8_t itf, char wanted); @@ -109,6 +112,7 @@ bool tud_cdc_n_write_clear (uint8_t itf); static inline bool tud_cdc_connected (void); static inline uint8_t tud_cdc_get_line_state (void); static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding); +static inline bool tud_cdc_send_uart_state (cdc_uart_state_t state); static inline void tud_cdc_set_wanted_char (char wanted); static inline uint32_t tud_cdc_available (void); @@ -180,6 +184,11 @@ static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding) tud_cdc_n_get_line_coding(0, coding); } +static inline bool tud_cdc_send_uart_state (cdc_uart_state_t state) +{ + return tud_cdc_n_send_uart_state(0, state); +} + static inline void tud_cdc_set_wanted_char (char wanted) { tud_cdc_n_set_wanted_char(0, wanted); From 418b8b2f133d695362c735f271c966af10b5d251 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Apr 2024 01:17:50 +0200 Subject: [PATCH 040/382] Add uart status notif to cdc_dual_ports example. --- examples/device/cdc_dual_ports/src/main.c | 11 ++++++++++- examples/device/cdc_dual_ports/src/usb_descriptors.c | 8 ++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/examples/device/cdc_dual_ports/src/main.c b/examples/device/cdc_dual_ports/src/main.c index 1167a5d50..2190b984a 100644 --- a/examples/device/cdc_dual_ports/src/main.c +++ b/examples/device/cdc_dual_ports/src/main.c @@ -94,7 +94,6 @@ void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } - //--------------------------------------------------------------------+ // USB CDC //--------------------------------------------------------------------+ @@ -115,6 +114,16 @@ static void cdc_task(void) { echo_serial_port(0, buf, count); echo_serial_port(1, buf, count); } + + // Press on-board button to send Uart status notification + static uint32_t btn_prev = 0; + static cdc_uart_state_t state = {0}; + uint32_t btn = board_button_read(); + if (!btn_prev && btn) { + state.bTxCarrier ^= 1; + tud_cdc_send_uart_state(state); + } + btn_prev = btn; } } } diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index de2505c07..76907de09 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -136,10 +136,10 @@ uint8_t const desc_fs_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 10, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 10, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64), }; #if TUD_OPT_HIGH_SPEED @@ -151,10 +151,10 @@ uint8_t const desc_hs_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 10, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 10, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512), }; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed From 965e26de1dcbd87c3b0e371857bc4ad0b9b3e840 Mon Sep 17 00:00:00 2001 From: Deadman Date: Wed, 28 Feb 2024 00:00:55 +0100 Subject: [PATCH 041/382] add support for native SAMD HCD --- hw/bsp/samd21/family.c | 16 +- hw/bsp/samd21/family.cmake | 1 + hw/bsp/samd21/family.mk | 1 + hw/bsp/samd5x_e5x/family.c | 33 +- hw/bsp/samd5x_e5x/family.cmake | 1 + hw/bsp/samd5x_e5x/family.mk | 1 + src/portable/microchip/samd/hcd_samd.c | 767 +++++++++++++++++++++++++ 7 files changed, 806 insertions(+), 14 deletions(-) create mode 100644 src/portable/microchip/samd/hcd_samd.c diff --git a/hw/bsp/samd21/family.c b/hw/bsp/samd21/family.c index 7ca20c458..257794058 100644 --- a/hw/bsp/samd21/family.c +++ b/hw/bsp/samd21/family.c @@ -60,7 +60,13 @@ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ void USB_Handler(void) { +#if CFG_TUD_ENABLED tud_int_handler(0); +#endif + +#if CFG_TUH_ENABLED && !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) + tuh_int_handler(0); +#endif } //--------------------------------------------------------------------+ @@ -140,8 +146,14 @@ void board_init(void) { gpio_set_pin_function(PIN_PA19, PINMUX_PA19F_TCC0_WO3); _gclk_enable_channel(TCC0_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); -#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 - max3421_init(); +#if CFG_TUH_ENABLED + #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + max3421_init(); + #else + // VBUS Power + gpio_set_pin_direction(PIN_PA28, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA28, true); + #endif #endif } diff --git a/hw/bsp/samd21/family.cmake b/hw/bsp/samd21/family.cmake index c836b85d9..ef9a8adb4 100644 --- a/hw/bsp/samd21/family.cmake +++ b/hw/bsp/samd21/family.cmake @@ -99,6 +99,7 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_SAMD21 ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC ${TOP}/src/portable/microchip/samd/dcd_samd.c + ${TOP}/src/portable/microchip/samd/hcd_samd.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) diff --git a/hw/bsp/samd21/family.mk b/hw/bsp/samd21/family.mk index 08c5c5b0e..a2c37b2b6 100644 --- a/hw/bsp/samd21/family.mk +++ b/hw/bsp/samd21/family.mk @@ -23,6 +23,7 @@ LDFLAGS_CLANG += SRC_C += \ src/portable/microchip/samd/dcd_samd.c \ + src/portable/microchip/samd/hcd_samd.c \ ${SDK_DIR}/gcc/gcc/startup_samd21.c \ ${SDK_DIR}/gcc/system_samd21.c \ ${SDK_DIR}/hal/src/hal_atomic.c \ diff --git a/hw/bsp/samd5x_e5x/family.c b/hw/bsp/samd5x_e5x/family.c index abaee353b..3b842e819 100644 --- a/hw/bsp/samd5x_e5x/family.c +++ b/hw/bsp/samd5x_e5x/family.c @@ -56,21 +56,24 @@ //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void USB_0_Handler(void) { +TU_ATTR_ALWAYS_INLINE inline void USB_Any_Handler(void) +{ +#if CFG_TUD_ENABLED tud_int_handler(0); +#endif + +#if CFG_TUH_ENABLED && !CFG_TUH_MAX3421 + tuh_int_handler(0); +#endif } -void USB_1_Handler(void) { - tud_int_handler(0); -} +void USB_0_Handler(void) { USB_Any_Handler(); } -void USB_2_Handler(void) { - tud_int_handler(0); -} +void USB_1_Handler(void) { USB_Any_Handler(); } -void USB_3_Handler(void) { - tud_int_handler(0); -} +void USB_2_Handler(void) { USB_Any_Handler(); } + +void USB_3_Handler(void) { USB_Any_Handler(); } //--------------------------------------------------------------------+ // Implementation @@ -138,8 +141,14 @@ void board_init(void) { gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM); gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP); -#if CFG_TUH_ENABLED && CFG_TUH_MAX3421 - max3421_init(); +#if CFG_TUH_ENABLED + #if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 + max3421_init(); + #else + // VBUS Power + gpio_set_pin_direction(PIN_PA28, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA28, true); + #endif #endif } diff --git a/hw/bsp/samd5x_e5x/family.cmake b/hw/bsp/samd5x_e5x/family.cmake index fd95ce10e..9a237f0dc 100644 --- a/hw/bsp/samd5x_e5x/family.cmake +++ b/hw/bsp/samd5x_e5x/family.cmake @@ -96,6 +96,7 @@ function(family_configure_example TARGET RTOS) family_add_tinyusb(${TARGET} OPT_MCU_SAMD51 ${RTOS}) target_sources(${TARGET}-tinyusb PUBLIC ${TOP}/src/portable/microchip/samd/dcd_samd.c + ${TOP}/src/portable/microchip/samd/hcd_samd.c ) target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) diff --git a/hw/bsp/samd5x_e5x/family.mk b/hw/bsp/samd5x_e5x/family.mk index 9b1a23db4..f0a4a3f00 100644 --- a/hw/bsp/samd5x_e5x/family.mk +++ b/hw/bsp/samd5x_e5x/family.mk @@ -18,6 +18,7 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/microchip/samd/dcd_samd.c \ + src/portable/microchip/samd/hcd_samd.c \ ${SDK_DIR}/gcc/gcc/startup_${SAM_FAMILY}.c \ ${SDK_DIR}/gcc/system_${SAM_FAMILY}.c \ ${SDK_DIR}/hpl/gclk/hpl_gclk.c \ diff --git a/src/portable/microchip/samd/hcd_samd.c b/src/portable/microchip/samd/hcd_samd.c new file mode 100644 index 000000000..cecaee0b0 --- /dev/null +++ b/src/portable/microchip/samd/hcd_samd.c @@ -0,0 +1,767 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 ChrisDeadman + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if CFG_TUH_ENABLED && \ + !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) && \ + (CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ + CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ + CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21) + +#include "host/hcd.h" +#include "sam.h" + +/*------------------------------------------------------------------*/ +/* MACRO TYPEDEF CONSTANT ENUM + *------------------------------------------------------------------*/ +#define USB_HOST_PTYPE_DIS 0x0 +#define USB_HOST_PTYPE_CTRL 0x1 +#define USB_HOST_PTYPE_ISO 0x2 +#define USB_HOST_PTYPE_BULK 0x3 +#define USB_HOST_PTYPE_INT 0x4 +#define USB_HOST_PTYPE_EXT 0x5 + +#define USB_HOST_PCFG_PTOKEN_SETUP 0x0 +#define USB_HOST_PCFG_PTOKEN_IN 0x1 +#define USB_HOST_PCFG_PTOKEN_OUT 0x2 + +#define USB_PCKSIZE_ENUM(size) \ + ((size) >= 1024 ? 7 \ + : (size) >= 1023 ? 7 \ + : (size) > 256 ? 6 \ + : (size) > 128 ? 5 \ + : (size) > 64 ? 4 \ + : (size) > 32 ? 3 \ + : (size) > 16 ? 2 \ + : (size) > 8 ? 1 \ + : 0) + +// Uncomment to use fake frame number. +// Low-Speed devices stall FNUM during enumeration :/ +// #define HCD_SAMD_FAKE_FNUM + +typedef struct { + uint8_t dev_addr; + uint8_t ep_addr; + uint16_t max_packet_size; + uint16_t xfer_length; + uint16_t xfer_remaining; +} usb_pipe_status_t; + +CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static volatile UsbHostDescriptor usb_pipe_table[USB_PIPE_NUM]; + +CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static volatile usb_pipe_status_t usb_pipe_status_table[USB_PIPE_NUM]; + +CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static volatile uint32_t fake_fnum; + +static uint8_t samd_configure_pipe(uint8_t dev_addr, uint8_t ep_addr) +{ + uint8_t pipe; + uint8_t token; + volatile usb_pipe_status_t* pipe_status; + bool same_addr = false; + bool same_ep_addr = false; + + // evaluate pipe token + token = (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) ? USB_HOST_PCFG_PTOKEN_IN + : tu_edpt_number(ep_addr) == 0 ? USB_HOST_PCFG_PTOKEN_SETUP + : USB_HOST_PCFG_PTOKEN_OUT; + + TU_LOG3("samd_configure_pipe(token=%02X, dev_addr=%02X, ep_addr=%02X)=", token, dev_addr, ep_addr); + + // find already allocated pipe + for (pipe = 0; pipe < USB_PIPE_NUM; pipe++) { + pipe_status = &usb_pipe_status_table[pipe]; + same_addr = (pipe_status->dev_addr == dev_addr); + same_ep_addr = (tu_edpt_number(pipe_status->ep_addr) == tu_edpt_number(ep_addr)); + if (same_ep_addr && (same_addr || (tu_edpt_number(ep_addr) == 0))) { + break; + } + } + + // allocate from pool of free pipes + if (pipe >= USB_PIPE_NUM) { + for (pipe = 0; pipe < USB_PIPE_NUM; pipe++) { + pipe_status = &usb_pipe_status_table[pipe]; + // found a free pipe + if (pipe_status->dev_addr >= UINT8_MAX) { + break; + } + } + } + + // no pipe available :( + if (pipe >= USB_PIPE_NUM) { + TU_LOG3("ERR_NO_PIPE\r\n"); + return pipe; + } + TU_LOG3("%d\r\n", pipe); + + // no transfer should be in progress + TU_ASSERT(((USB->HOST.HostPipe[pipe].PCFG.bit.PTYPE == USB_HOST_PTYPE_DIS) || + USB->HOST.HostPipe[pipe].PSTATUS.bit.PFREEZE == 1), + USB_PIPE_NUM); + + // update addr and ep_addr + pipe_status->dev_addr = dev_addr; + pipe_status->ep_addr = ep_addr; + usb_pipe_table[pipe].HostDescBank[0].CTRL_PIPE.bit.PDADDR = dev_addr; + usb_pipe_table[pipe].HostDescBank[0].CTRL_PIPE.bit.PEPNUM = tu_edpt_number(ep_addr); + + // token specific configuration + USB->HOST.HostPipe[pipe].PCFG.bit.PTOKEN = token; + USB->HOST.HostPipe[pipe].PINTENCLR.reg = USB_HOST_PINTENCLR_MASK; + if (token == USB_HOST_PCFG_PTOKEN_SETUP) { + USB->HOST.HostPipe[pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_DTGL; + USB->HOST.HostPipe[pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_TXSTP; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_STALL; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_TRFAIL; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_PERR; + } else if (token == USB_HOST_PCFG_PTOKEN_IN) { + USB->HOST.HostPipe[pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_TRCPT_Msk; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_STALL; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_TRFAIL; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_PERR; + } else { + USB->HOST.HostPipe[pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_TRCPT_Msk; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_STALL; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_TRFAIL; + USB->HOST.HostPipe[pipe].PINTENSET.reg = USB_HOST_PINTENSET_PERR; + } + + return pipe; +} + +static void samd_free_pipe(uint8_t pipe) +{ + volatile usb_pipe_status_t* pipe_status = &usb_pipe_status_table[pipe]; + pipe_status->dev_addr = UINT8_MAX; + pipe_status->ep_addr = UINT8_MAX; + pipe_status->max_packet_size = 0; + pipe_status->xfer_length = 0; + pipe_status->xfer_remaining = 0; + + USB->HOST.HostPipe[pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE; + USB->HOST.HostPipe[pipe].PCFG.reg &= ~USB_HOST_PCFG_PTYPE_Msk; + USB->HOST.HostPipe[pipe].PINTENCLR.reg = USB_HOST_PINTENCLR_MASK; + memset((uint8_t*) &usb_pipe_table[pipe], 0, sizeof(usb_pipe_table[pipe])); +} + +static void samd_free_all_pipes(void) +{ + for (uint8_t pipe = 0; pipe < USB_PIPE_NUM; pipe++) { + samd_free_pipe(pipe); + } +} + +static bool samd_on_xfer(uint8_t pipe, xfer_result_t xfer_result) +{ + uint16_t xfer_delta; + bool xfer_complete; + volatile usb_pipe_status_t* pipe_status = &usb_pipe_status_table[pipe]; + + // freeze the pipe + USB->HOST.HostPipe[pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE; + + // get number of transferred bytes + if (xfer_result == XFER_RESULT_SUCCESS) { + xfer_delta = usb_pipe_table[pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT; + } else { + xfer_delta = 0; + } + + TU_LOG3( + "samd_on_xfer(%d, result=%d, xdelta=%d, rem=%d)\r\n", xfer_result, pipe, xfer_delta, pipe_status->xfer_remaining); + + // update pipe status + if (xfer_delta > pipe_status->xfer_remaining) { + xfer_delta = pipe_status->xfer_remaining; + } + pipe_status->xfer_remaining -= xfer_delta; + pipe_status->xfer_length += xfer_delta; + + // last packet handling + if (xfer_delta < pipe_status->max_packet_size) { + pipe_status->xfer_remaining = 0; + } + + // transfer complete + xfer_complete = (xfer_result != XFER_RESULT_SUCCESS) || (pipe_status->xfer_remaining == 0); + if (xfer_complete) { + return true; + } + + // continue receiving + if (tu_edpt_dir(pipe_status->ep_addr) == TUSB_DIR_IN) { + usb_pipe_table[pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0; + USB->HOST.HostPipe[pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY; + } + // continue sending + else { + usb_pipe_table[pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = + (pipe_status->xfer_remaining < pipe_status->max_packet_size) ? pipe_status->xfer_remaining + : pipe_status->max_packet_size; + USB->HOST.HostPipe[pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY; + } + + // advance packet buffer + usb_pipe_table[pipe].HostDescBank[0].ADDR.reg += xfer_delta; + + // start next transfer + USB->HOST.HostPipe[pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE; + + return false; +} + +//--------------------------------------------------------------------+ +// Controller API +//--------------------------------------------------------------------+ + +// Interrupt Handler +void hcd_int_handler(uint8_t rhport, bool in_isr) +{ + (void) rhport; + + uint16_t int_flags; + uint8_t pint_flags; + xfer_result_t xfer_result; + volatile usb_pipe_status_t* pipe_status; + + // + // Check INTFLAG + // + int_flags = USB->HOST.INTFLAG.reg; + if (int_flags & USB_HOST_INTFLAG_HSOF) { + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_HSOF; + } + if (int_flags & USB_HOST_INTFLAG_RST) { + TU_LOG2("USB_HOST_INTFLAG_RST\r\n"); + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RST; + } + if (int_flags & USB_HOST_INTFLAG_WAKEUP) { + TU_LOG3("USB_HOST_INTFLAG_WAKEUP\r\n"); + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_WAKEUP; + } + if (int_flags & USB_HOST_INTFLAG_DNRSM) { + TU_LOG3("USB_HOST_INTFLAG_DNRSM\r\n"); + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DNRSM; + } + if (int_flags & USB_HOST_INTFLAG_UPRSM) { + TU_LOG3("USB_HOST_INTFLAG_UPRSM\r\n"); + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_UPRSM; + } + if (int_flags & USB_HOST_INTFLAG_RAMACER) { + TU_LOG1("USB_HOST_INTFLAG_RAMACER\r\n"); + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RAMACER; + } + if (int_flags & USB_HOST_INTFLAG_DCONN) { + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DCONN; + hcd_event_device_attach(rhport, in_isr); + } + if (int_flags & USB_HOST_INTFLAG_DDISC) { + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_DDISC; + hcd_event_device_remove(rhport, in_isr); + } + + // handle pipe interrupts + for (uint8_t pipe = 0; pipe < USB_PIPE_NUM; pipe++) { + // get pipe handle + pipe_status = &usb_pipe_status_table[pipe]; + if (pipe_status->dev_addr >= UINT8_MAX) { + continue; + } + + // + // Check PINTFLAG + // + pint_flags = USB->HOST.HostPipe[pipe].PINTFLAG.reg; + xfer_result = XFER_RESULT_INVALID; + if (pint_flags & USB_HOST_PINTFLAG_TRCPT0) { + USB->HOST.HostPipe[pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_TRCPT0; + xfer_result = XFER_RESULT_SUCCESS; + } + if (pint_flags & USB_HOST_PINTFLAG_TRCPT1) { + USB->HOST.HostPipe[pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_TRCPT1; + xfer_result = XFER_RESULT_SUCCESS; + } + if (pint_flags & USB_HOST_PINTFLAG_TXSTP) { + USB->HOST.HostPipe[pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_TXSTP; + xfer_result = XFER_RESULT_SUCCESS; + } + if (pint_flags & USB_HOST_PINTFLAG_STALL) { + TU_LOG2("USB_HOST_PINTFLAG_STALL\r\n"); + USB->HOST.HostPipe[pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_STALL; + xfer_result = XFER_RESULT_STALLED; + } + if (pint_flags & USB_HOST_PINTFLAG_TRFAIL) { + USB->HOST.HostPipe[pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_TRFAIL; + if (usb_pipe_table[pipe].HostDescBank[0].STATUS_BK.reg & USB_HOST_STATUS_BK_ERRORFLOW) { + TU_LOG1("USB_HOST_STATUS_BK_ERRORFLOW\r\n"); + xfer_result = XFER_RESULT_FAILED; + } else if (usb_pipe_table[pipe].HostDescBank[0].STATUS_BK.reg & USB_HOST_STATUS_BK_CRCERR) { + TU_LOG1("USB_HOST_STATUS_BK_CRCERR\r\n"); + xfer_result = XFER_RESULT_FAILED; + } else { + // SAMD Quirk #1: + // Likes to report TRFAIL for no apparent reason -> ignore + } + } + if (pint_flags & USB_HOST_PINTFLAG_PERR) { + USB->HOST.HostPipe[pipe].PINTFLAG.reg = USB_HOST_PINTFLAG_PERR; + // Handled by STATUS_PIPE checks below + } + + // + // Check STATUS_PIPE + // + if (usb_pipe_table[pipe].HostDescBank[0].STATUS_PIPE.reg & USB_HOST_STATUS_PIPE_DTGLER) { + TU_LOG1("USB_HOST_STATUS_PIPE_DTGLER\r\n"); + usb_pipe_table[pipe].HostDescBank[0].STATUS_PIPE.reg &= ~USB_HOST_STATUS_PIPE_DTGLER; + xfer_result = XFER_RESULT_FAILED; + } + if (usb_pipe_table[pipe].HostDescBank[0].STATUS_PIPE.reg & USB_HOST_STATUS_PIPE_DAPIDER) { + TU_LOG1("USB_HOST_STATUS_PIPE_DAPIDER\r\n"); + usb_pipe_table[pipe].HostDescBank[0].STATUS_PIPE.reg &= ~USB_HOST_STATUS_PIPE_DAPIDER; + xfer_result = XFER_RESULT_FAILED; + } + if (usb_pipe_table[pipe].HostDescBank[0].STATUS_PIPE.reg & USB_HOST_STATUS_PIPE_PIDER) { + TU_LOG1("USB_HOST_STATUS_PIPE_PIDER\r\n"); + usb_pipe_table[pipe].HostDescBank[0].STATUS_PIPE.reg &= ~USB_HOST_STATUS_PIPE_PIDER; + xfer_result = XFER_RESULT_FAILED; + } + if (usb_pipe_table[pipe].HostDescBank[0].STATUS_PIPE.reg & USB_HOST_STATUS_PIPE_CRC16ER) { + TU_LOG1("USB_HOST_STATUS_PIPE_CRC16ER\r\n"); + usb_pipe_table[pipe].HostDescBank[0].STATUS_PIPE.reg &= ~USB_HOST_STATUS_PIPE_CRC16ER; + xfer_result = XFER_RESULT_FAILED; + } + if (usb_pipe_table[pipe].HostDescBank[0].STATUS_PIPE.reg & USB_HOST_STATUS_PIPE_TOUTER) { + usb_pipe_table[pipe].HostDescBank[0].STATUS_PIPE.reg &= ~USB_HOST_STATUS_PIPE_TOUTER; + + if ((USB->HOST.HostPipe[pipe].PCFG.bit.PTYPE == USB_HOST_PTYPE_INT) && + (tu_edpt_dir(pipe_status->ep_addr) == TUSB_DIR_IN)) { + // ignore timeouts from INT pipes + } else { + if (xfer_result == XFER_RESULT_INVALID) { + xfer_result = XFER_RESULT_TIMEOUT; + } + } + } + + // prevent PERR from too high error counts, that is handled by TinyUSB anyways + usb_pipe_table[pipe].HostDescBank[0].STATUS_PIPE.bit.ERCNT = 0; + + // no updates + if (xfer_result == XFER_RESULT_INVALID) { + continue; + } + + // continue / complete transfer + if (samd_on_xfer(pipe, xfer_result)) { + hcd_event_xfer_complete(pipe_status->dev_addr, pipe_status->ep_addr, pipe_status->xfer_length, xfer_result, true); + } + } +} + +// Initialize controller to host mode +bool hcd_init(uint8_t rhport) +{ + TU_ASSERT(rhport == 0); + + fake_fnum = 0; + + // reset to get in a clean state. + USB->HOST.CTRLA.bit.SWRST = 1; + while (USB->HOST.SYNCBUSY.bit.SWRST == 0) + ; + while (USB->HOST.SYNCBUSY.bit.SWRST == 1) + ; + + // load pad calibration + USB->HOST.PADCAL.bit.TRANSP = (*((uint32_t*) USB_FUSES_TRANSP_ADDR) & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos; + USB->HOST.PADCAL.bit.TRANSN = (*((uint32_t*) USB_FUSES_TRANSN_ADDR) & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos; + USB->HOST.PADCAL.bit.TRIM = (*((uint32_t*) USB_FUSES_TRIM_ADDR) & USB_FUSES_TRIM_Msk) >> USB_FUSES_TRIM_Pos; + + USB->HOST.QOSCTRL.bit.CQOS = 3; // High Quality + USB->HOST.QOSCTRL.bit.DQOS = 3; // High Quality + + // configure host-mode + samd_free_all_pipes(); // initializes pipe handles and usb_pipe_table + USB->HOST.DESCADD.reg = (uint32_t) (&usb_pipe_table[0]); + USB->HOST.CTRLB.reg = USB_HOST_CTRLB_SPDCONF_NORMAL | USB_HOST_CTRLB_VBUSOK; + USB->HOST.CTRLA.reg = USB_CTRLA_MODE_HOST | USB_CTRLA_ENABLE | USB_CTRLA_RUNSTDBY; + while (USB->HOST.SYNCBUSY.bit.ENABLE == 1) + ; + + // enable basic USB interrupts + USB->HOST.INTFLAG.reg |= USB->HOST.INTFLAG.reg; // clear pending + USB->HOST.INTENCLR.reg = USB_HOST_INTENCLR_MASK; + USB->HOST.INTENSET.reg = USB_HOST_INTENSET_DCONN; + USB->HOST.INTENSET.reg = USB_HOST_INTENSET_DDISC; + USB->HOST.INTENSET.reg = USB_HOST_INTENSET_WAKEUP; + USB->HOST.INTENSET.reg = USB_HOST_INTENSET_RST; + + return true; +} + +#if CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X + +// Enable USB interrupt +void hcd_int_enable(uint8_t rhport) +{ + (void) rhport; + NVIC_EnableIRQ(USB_0_IRQn); + NVIC_EnableIRQ(USB_1_IRQn); + NVIC_EnableIRQ(USB_2_IRQn); + NVIC_EnableIRQ(USB_3_IRQn); +} + +// Disable USB interrupt +void hcd_int_disable(uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ(USB_3_IRQn); + NVIC_DisableIRQ(USB_2_IRQn); + NVIC_DisableIRQ(USB_1_IRQn); + NVIC_DisableIRQ(USB_0_IRQn); +} + +#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ + CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21 + +// Enable USB interrupt +void hcd_int_enable(uint8_t rhport) +{ + (void) rhport; + NVIC_EnableIRQ(USB_IRQn); +} + +// Disable USB interrupt +void hcd_int_disable(uint8_t rhport) +{ + (void) rhport; + NVIC_DisableIRQ(USB_IRQn); +} + +#else + +#error "No implementation available for hcd_int_enable / hcd_int_disable" + +#endif + +// Get frame number (1ms) +uint32_t hcd_frame_number(uint8_t rhport) +{ + (void) rhport; + +// SAMD Quirk #2: +// FNUM is stalled before enumeration of Low-Speed devices. +// internal frame counter can be used as workaround (not very accurate) +#ifdef HCD_SAMD_FAKE_FNUM + uint8_t start, current, prev; + uint8_t loop_count = (USB->HOST.STATUS.bit.SPEED == TUSB_SPEED_HIGH) ? 8 : 1; + for (uint8_t i = 0; i < loop_count; i++) { + start = USB->HOST.FLENHIGH.reg; + current = start; + // wait until wrap-around + prev = current; + while (current <= start) { + current = USB->HOST.FLENHIGH.reg; + if (current > prev) + break; + prev = current; + } + // wait until start is reached again + prev = current; + while (current > start) { + current = USB->HOST.FLENHIGH.reg; + if (current > prev) + break; + prev = current; + } + } + fake_fnum += 1; + return fake_fnum; +#else + return USB->HOST.FNUM.bit.FNUM; +#endif // HCD_SAMD_FAKE_FNUM +} + +//--------------------------------------------------------------------+ +// Port API +//--------------------------------------------------------------------+ + +// Get the current connect status of roothub port +bool hcd_port_connect_status(uint8_t rhport) +{ + TU_ASSERT(rhport == 0); + return USB->HOST.STATUS.bit.LINESTATE != 0; +} + +// Reset USB bus on the port. Return immediately, bus reset sequence may not be +// complete. Some port would require hcd_port_reset_end() to be invoked after 10ms to +// complete the reset sequence. +void hcd_port_reset(uint8_t rhport) +{ + hcd_int_disable(rhport); + samd_free_all_pipes(); + USB->HOST.INTFLAG.reg |= USB->HOST.INTFLAG.reg; // clear pending + USB->HOST.CTRLB.bit.BUSRESET = 1; + fake_fnum = 0; +} + +// Complete bus reset sequence, may be required by some controllers +void hcd_port_reset_end(uint8_t rhport) +{ + while (USB->HOST.INTFLAG.bit.RST == 0) + ; + USB->HOST.INTFLAG.reg = USB_HOST_INTFLAG_RST; + USB->HOST.CTRLB.bit.SOFE = 1; + hcd_int_enable(rhport); +} + +// Get port link speed +tusb_speed_t hcd_port_speed_get(uint8_t rhport) +{ + (void) rhport; + + switch (USB->HOST.STATUS.bit.SPEED) { + case 0: + return TUSB_SPEED_FULL; + case 1: + return TUSB_SPEED_LOW; + case 2: + return TUSB_SPEED_HIGH; + default: + return TUSB_SPEED_INVALID; + } +} + +// HCD closes all opened endpoints belong to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) +{ + (void) rhport; + + for (uint8_t pipe = 0; pipe < USB_PIPE_NUM; pipe++) { + volatile usb_pipe_status_t* pipe_status = &usb_pipe_status_table[pipe]; + if (pipe_status->dev_addr == dev_addr) { + samd_free_pipe(pipe); + } + } +} + +//--------------------------------------------------------------------+ +// Endpoints API +//--------------------------------------------------------------------+ + +// Open an endpoint +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* ep_desc) +{ + TU_ASSERT(rhport == 0); + + uint8_t pipe; + volatile usb_pipe_status_t* pipe_status; + const uint8_t ep_addr = ep_desc->bEndpointAddress; + const uint8_t bmAttributes = (ep_desc->bmAttributes.xfer) | + ((ep_desc->bmAttributes.sync) << 2) | + ((ep_desc->bmAttributes.usage) << 4); + + // configure the pipe + pipe = samd_configure_pipe(dev_addr, ep_addr); + if (pipe >= USB_PIPE_NUM) { + return false; + } + + // initial configuration + pipe_status = &usb_pipe_status_table[pipe]; + USB->HOST.HostPipe[pipe].PCFG.reg &= ~USB_HOST_PCFG_PTYPE_Msk; + USB->HOST.HostPipe[pipe].PCFG.bit.PTYPE = bmAttributes + 1; + USB->HOST.HostPipe[pipe].BINTERVAL.reg = ep_desc->bInterval; + USB->HOST.HostPipe[pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_DTGL; + USB->HOST.HostPipe[pipe].PINTENCLR.reg = USB_HOST_PINTENCLR_MASK; + pipe_status->max_packet_size = ep_desc->wMaxPacketSize; + usb_pipe_table[pipe].HostDescBank[0].PCKSIZE.bit.SIZE = USB_PCKSIZE_ENUM(pipe_status->max_packet_size); + usb_pipe_table[pipe].HostDescBank[0].PCKSIZE.bit.AUTO_ZLP = 0; + + return true; +} + +// Submit a special transfer to send 8-byte Setup Packet, when complete +// hcd_event_xfer_complete() must be invoked +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) +{ + TU_ASSERT(rhport == 0); + + uint8_t pipe; + volatile usb_pipe_status_t* pipe_status; + + // configure the pipe + pipe = samd_configure_pipe(dev_addr, 0); + if (pipe >= USB_PIPE_NUM) { + return false; + } + + // prepare transfer + pipe_status = &usb_pipe_status_table[pipe]; + usb_pipe_table[pipe].HostDescBank[0].ADDR.reg = (uint32_t) setup_packet; + pipe_status->xfer_remaining = 8; + pipe_status->xfer_length = 0; + usb_pipe_table[pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 8; + usb_pipe_table[pipe].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 0; + USB->HOST.HostPipe[pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY; + + // clear pending interrupts + USB->HOST.HostPipe[pipe].PINTFLAG.reg |= USB->HOST.HostPipe[pipe].PINTFLAG.reg; + + // begin transfer + USB->HOST.HostPipe[pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE; + + return true; +} + +// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t* buffer, uint16_t buflen) +{ + TU_ASSERT(rhport == 0); + + uint8_t pipe; + volatile usb_pipe_status_t* pipe_status; + + // configure the pipe + pipe = samd_configure_pipe(dev_addr, ep_addr); + if (pipe >= USB_PIPE_NUM) { + return false; + } + + // prepare transfer + pipe_status = &usb_pipe_status_table[pipe]; + usb_pipe_table[pipe].HostDescBank[0].ADDR.reg = (uint32_t) buffer; + pipe_status->xfer_remaining = buflen; + pipe_status->xfer_length = 0; + // receive data + if (tu_edpt_dir(pipe_status->ep_addr) == TUSB_DIR_IN) { + usb_pipe_table[pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0; + usb_pipe_table[pipe].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = pipe_status->max_packet_size; + USB->HOST.HostPipe[pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_BK0RDY; + } + // send data + else { + usb_pipe_table[pipe].HostDescBank[0].PCKSIZE.bit.BYTE_COUNT = + (pipe_status->xfer_remaining < pipe_status->max_packet_size) ? pipe_status->xfer_remaining + : pipe_status->max_packet_size; + usb_pipe_table[pipe].HostDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 0; + USB->HOST.HostPipe[pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_BK0RDY; + } + + // clear pending interrupts + USB->HOST.HostPipe[pipe].PINTFLAG.reg |= USB->HOST.HostPipe[pipe].PINTFLAG.reg; + + // begin transfer + USB->HOST.HostPipe[pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_PFREEZE; + + return true; +} + +// Abort a queued transfer. Note: it can only abort transfer that has not been +// started Return true if a queued transfer is aborted, false if there is no transfer +// to abort +bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) +{ + TU_ASSERT(rhport == 0); + + uint8_t pipe; + volatile usb_pipe_status_t* pipe_status; + + TU_LOG3("hcd_edpt_abort_xfer(dev_addr=%02X, ep_addr=%02X)=", dev_addr, ep_addr); + + // find the pipe + for (pipe = 0; pipe < USB_PIPE_NUM; pipe++) { + pipe_status = &usb_pipe_status_table[pipe]; + if ((pipe_status->dev_addr == dev_addr) && (pipe_status->ep_addr == ep_addr)) { + break; + } + } + + // pipe not found + if (pipe >= USB_PIPE_NUM) { + TU_LOG3("ERR_NO_PIPE\r\n"); + return false; + } + TU_LOG3("%d\r\n", pipe); + + // no transfer in progress + if (USB->HOST.HostPipe[pipe].PSTATUS.bit.PFREEZE == 1) { + return false; + } + + // abort the transfer + USB->HOST.HostPipe[pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE; + pipe_status = &usb_pipe_status_table[pipe]; + pipe_status->xfer_length = 0; + pipe_status->xfer_remaining = 0; + + return true; +} + +// clear stall, data toggle is also reset to DATA0 +bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) +{ + TU_ASSERT(rhport == 0); + + uint8_t pipe; + volatile usb_pipe_status_t* pipe_status; + + TU_LOG3("hcd_edpt_clear_stall(dev_addr=%02X, ep_addr=%02X)=", dev_addr, ep_addr); + + // find the pipe + for (pipe = 0; pipe < USB_PIPE_NUM; pipe++) { + pipe_status = &usb_pipe_status_table[pipe]; + if ((pipe_status->dev_addr == dev_addr) && (pipe_status->ep_addr == ep_addr)) { + break; + } + } + + // pipe not found + if (pipe >= USB_PIPE_NUM) { + TU_LOG3("ERR_NO_PIPE\r\n"); + return false; + } + TU_LOG3("%d\r\n", pipe); + + // clear pending interrupts + USB->HOST.HostPipe[pipe].PINTFLAG.reg |= USB->HOST.HostPipe[pipe].PINTFLAG.reg; + + // clear stalled state + USB->HOST.HostPipe[pipe].PSTATUSSET.reg = USB_HOST_PSTATUSSET_PFREEZE; + USB->HOST.HostPipe[pipe].PSTATUSCLR.reg = USB_HOST_PSTATUSCLR_DTGL; + + return true; +} + +#endif From dee6b369235e3440f9237ae0e74f81edca95f6b7 Mon Sep 17 00:00:00 2001 From: Roman Leonov Date: Wed, 11 Dec 2024 11:35:52 +0100 Subject: [PATCH 042/382] feature(tusb): Added teardown API --- src/tusb.c | 34 ++++++++++++++++++++++++++++++++++ src/tusb.h | 14 ++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/tusb.c b/src/tusb.c index 85ab1d6ae..1549419c8 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -136,6 +136,40 @@ void tusb_int_handler(uint8_t rhport, bool in_isr) { #endif } +bool tusb_rhport_teardown(uint8_t rhport) { + // backward compatible call with tusb_init(void) + #if defined(TUD_OPT_RHPORT) || defined(TUH_OPT_RHPORT) + #if CFG_TUD_ENABLED && defined(TUD_OPT_RHPORT) + // deinit device stack, CFG_TUSB_RHPORTx_MODE must be defined + TU_ASSERT( tud_deinit(TUD_OPT_RHPORT) ); + _tusb_rhport_role[TUD_OPT_RHPORT] = TUSB_ROLE_INVALID; + #endif + + #if CFG_TUH_ENABLED && defined(TUH_OPT_RHPORT) + // deinit host stack CFG_TUSB_RHPORTx_MODE must be defined + TU_ASSERT( tuh_deinit(TUH_OPT_RHPORT) ); + _tusb_rhport_role[TUH_OPT_RHPORT] = TUSB_ROLE_INVALID; + #endif + + return true; + #endif + + // new API with explicit rhport and role + TU_ASSERT(rhport < TUP_USBIP_CONTROLLER_NUM); + + #if CFG_TUD_ENABLED + TU_ASSERT( tud_deinit(rhport) ); + _tusb_rhport_role[rhport] = TUSB_ROLE_INVALID; + #endif + + #if CFG_TUH_ENABLED + TU_ASSERT( tuh_deinit(rhport) ); + _tusb_rhport_role[rhport] = TUSB_ROLE_INVALID; + #endif + + return true; +} + //--------------------------------------------------------------------+ // Descriptor helper //--------------------------------------------------------------------+ diff --git a/src/tusb.h b/src/tusb.h index cb6021b33..2b122c302 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -154,14 +154,24 @@ bool tusb_inited(void); // Called to handle usb interrupt/event. tusb_init(rhport, role) must be called before void tusb_int_handler(uint8_t rhport, bool in_isr); -// TODO -// bool tusb_teardown(void); +// Internal helper for backward compatibility with tusb_init(void) +bool tusb_rhport_teardown(uint8_t rhport); + +#if defined(TUD_OPT_RHPORT) || defined(TUH_OPT_RHPORT) + #define _tusb_teardown_arg0() tusb_rhport_teardown(0) +#else + #define _tusb_teardown_arg0() TU_VERIFY_STATIC(false, "CFG_TUSB_RHPORT0_MODE/CFG_TUSB_RHPORT1_MODE must be defined") +#endif + +#define _tusb_teardown_arg1(_rhport) tusb_rhport_teardown(_rhport) +#define tusb_teardown(...) TU_FUNC_OPTIONAL_ARG(_tusb_teardown, __VA_ARGS__) #else #define tusb_init(...) (false) #define tusb_int_handler(...) do {}while(0) #define tusb_inited() (false) +#define tusb_teardown(...) (false) #endif From 6d1ed1ed8658ef20f72c52666d68d88024265e9f Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 22 Jan 2025 22:35:49 +0100 Subject: [PATCH 043/382] Update deps. Signed-off-by: HiFiPhile --- docs/reference/dependencies.rst | 136 ++++++++++++++++---------------- tools/get_deps.py | 8 +- 2 files changed, 76 insertions(+), 68 deletions(-) diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index e124466da..41662c749 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -4,70 +4,72 @@ Dependencies MCU low-level peripheral driver and external libraries for building TinyUSB examples -======================================== ============================================================== ======================================== ==================================================================================================================================================================================================================================================================================================================================== -Local Path Repo Commit Required by -======================================== ============================================================== ======================================== ==================================================================================================================================================================================================================================================================================================================================== -hw/mcu/allwinner https://github.com/hathach/allwinner_driver.git 8e5e89e8e132c0fd90e72d5422e5d3d68232b756 fc100s -hw/mcu/analog/max32 https://github.com/analogdevicesinc/msdk.git b20b398d3e5e2007594e54a74ba3d2a2e50ddd75 max32650 max32666 max32690 max78002 -hw/mcu/bridgetek/ft9xx/ft90x-sdk https://github.com/BRTSG-FOSS/ft90x-sdk.git 91060164afe239fcb394122e8bf9eb24d3194eb1 brtmm90x -hw/mcu/broadcom https://github.com/adafruit/broadcom-peripherals.git 08370086080759ed54ac1136d62d2ad24c6fa267 broadcom_32bit broadcom_64bit -hw/mcu/gd/nuclei-sdk https://github.com/Nuclei-Software/nuclei-sdk.git 7eb7bfa9ea4fbeacfafe1d5f77d5a0e6ed3922e7 gd32vf103 -hw/mcu/infineon/mtb-xmclib-cat3 https://github.com/Infineon/mtb-xmclib-cat3.git daf5500d03cba23e68c2f241c30af79cd9d63880 xmc4000 -hw/mcu/microchip https://github.com/hathach/microchip_driver.git 9e8b37e307d8404033bb881623a113931e1edf27 sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg -hw/mcu/mindmotion/mm32sdk https://github.com/hathach/mm32sdk.git b93e856211060ae825216c6a1d6aa347ec758843 mm32 -hw/mcu/nordic/nrfx https://github.com/NordicSemiconductor/nrfx.git 7c47cc0a56ce44658e6da2458e86cd8783ccc4a2 nrf -hw/mcu/nuvoton https://github.com/majbthrd/nuc_driver.git 2204191ec76283371419fbcec207da02e1bc22fa nuc -hw/mcu/nxp/lpcopen https://github.com/hathach/nxp_lpcopen.git b41cf930e65c734d8ec6de04f1d57d46787c76ae lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 -hw/mcu/nxp/mcux-sdk https://github.com/hathach/mcux-sdk.git 144f1eb7ea8c06512e12f12b27383601c0272410 kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt -hw/mcu/raspberry_pi/Pico-PIO-USB https://github.com/sekigon-gonnoc/Pico-PIO-USB.git fe9133fc513b82cc3dc62c67cb51f2339cf29ef7 rp2040 -hw/mcu/renesas/fsp https://github.com/renesas/fsp.git edcc97d684b6f716728a60d7a6fea049d9870bd6 ra -hw/mcu/renesas/rx https://github.com/kkitayam/rx_device.git 706b4e0cf485605c32351e2f90f5698267996023 rx -hw/mcu/silabs/cmsis-dfp-efm32gg12b https://github.com/cmsis-packs/cmsis-dfp-efm32gg12b.git f1c31b7887669cb230b3ea63f9b56769078960bc efm32 -hw/mcu/sony/cxd56/spresense-exported-sdk https://github.com/sonydevworld/spresense-exported-sdk.git 2ec2a1538362696118dc3fdf56f33dacaf8f4067 spresense -hw/mcu/st/cmsis_device_c0 https://github.com/STMicroelectronics/cmsis_device_c0.git fb56b1b70c73b74eacda2a4bcc36886444364ab3 stm32c0 -hw/mcu/st/cmsis_device_f0 https://github.com/STMicroelectronics/cmsis_device_f0.git 2fc25ee22264bc27034358be0bd400b893ef837e stm32f0 -hw/mcu/st/cmsis_device_f1 https://github.com/STMicroelectronics/cmsis_device_f1.git 6601104a6397299b7304fd5bcd9a491f56cb23a6 stm32f1 -hw/mcu/st/cmsis_device_f2 https://github.com/STMicroelectronics/cmsis_device_f2.git 182fcb3681ce116816feb41b7764f1b019ce796f stm32f2 -hw/mcu/st/cmsis_device_f3 https://github.com/STMicroelectronics/cmsis_device_f3.git 5e4ee5ed7a7b6c85176bb70a9fd3c72d6eb99f1b stm32f3 -hw/mcu/st/cmsis_device_f4 https://github.com/STMicroelectronics/cmsis_device_f4.git 2615e866fa48fe1ff1af9e31c348813f2b19e7ec stm32f4 -hw/mcu/st/cmsis_device_f7 https://github.com/STMicroelectronics/cmsis_device_f7.git 25b0463439303b7a38f0d27b161f7d2f3c096e79 stm32f7 -hw/mcu/st/cmsis_device_g0 https://github.com/STMicroelectronics/cmsis_device_g0.git 3a23e1224417f3f2d00300ecd620495e363f2094 stm32g0 -hw/mcu/st/cmsis_device_g4 https://github.com/STMicroelectronics/cmsis_device_g4.git ce822adb1dc552b3aedd13621edbc7fdae124878 stm32g4 -hw/mcu/st/cmsis_device_h5 https://github.com/STMicroelectronics/cmsis_device_h5.git cd2d1d579743de57b88ccaf61a968b9c05848ffc stm32h5 -hw/mcu/st/cmsis_device_h7 https://github.com/STMicroelectronics/cmsis_device_h7.git 60dc2c913203dc8629dc233d4384dcc41c91e77f stm32h7 -hw/mcu/st/cmsis_device_l0 https://github.com/STMicroelectronics/cmsis_device_l0.git 69cd5999fd40ae6e546d4905b21635c6ca1bcb92 stm32l0 -hw/mcu/st/cmsis_device_l1 https://github.com/STMicroelectronics/cmsis_device_l1.git 7f16ec0a1c4c063f84160b4cc6bf88ad554a823e stm32l1 -hw/mcu/st/cmsis_device_l4 https://github.com/STMicroelectronics/cmsis_device_l4.git 6ca7312fa6a5a460b5a5a63d66da527fdd8359a6 stm32l4 -hw/mcu/st/cmsis_device_l5 https://github.com/STMicroelectronics/cmsis_device_l5.git d922865fc0326a102c26211c44b8e42f52c1e53d stm32l5 -hw/mcu/st/cmsis_device_u5 https://github.com/STMicroelectronics/cmsis_device_u5.git 5ad9797c54ec3e55eff770fc9b3cd4a1aefc1309 stm32u5 -hw/mcu/st/cmsis_device_wb https://github.com/STMicroelectronics/cmsis_device_wb.git 9c5d1920dd9fabbe2548e10561d63db829bb744f stm32wb -hw/mcu/st/stm32-mfxstm32l152 https://github.com/STMicroelectronics/stm32-mfxstm32l152.git 7f4389efee9c6a655b55e5df3fceef5586b35f9b stm32h7 -hw/mcu/st/stm32c0xx_hal_driver https://github.com/STMicroelectronics/stm32c0xx_hal_driver.git 41253e2f1d7ae4a4d0c379cf63f5bcf71fcf8eb3 stm32c0 -hw/mcu/st/stm32f0xx_hal_driver https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git 0e95cd88657030f640a11e690a8a5186c7712ea5 stm32f0 -hw/mcu/st/stm32f1xx_hal_driver https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git 1dd9d3662fb7eb2a7f7d3bc0a4c1dc7537915a29 stm32f1 -hw/mcu/st/stm32f2xx_hal_driver https://github.com/STMicroelectronics/stm32f2xx_hal_driver.git c75ace9b908a9aca631193ebf2466963b8ea33d0 stm32f2 -hw/mcu/st/stm32f3xx_hal_driver https://github.com/STMicroelectronics/stm32f3xx_hal_driver.git 1761b6207318ede021706e75aae78f452d72b6fa stm32f3 -hw/mcu/st/stm32f4xx_hal_driver https://github.com/STMicroelectronics/stm32f4xx_hal_driver.git 04e99fbdabd00ab8f370f377c66b0a4570365b58 stm32f4 -hw/mcu/st/stm32f7xx_hal_driver https://github.com/STMicroelectronics/stm32f7xx_hal_driver.git f7ffdf6bf72110e58b42c632b0a051df5997e4ee stm32f7 -hw/mcu/st/stm32g0xx_hal_driver https://github.com/STMicroelectronics/stm32g0xx_hal_driver.git e911b12c7f67084d7f6b76157a4c0d4e2ec3779c stm32g0 -hw/mcu/st/stm32g4xx_hal_driver https://github.com/STMicroelectronics/stm32g4xx_hal_driver.git 8b4518417706d42eef5c14e56a650005abf478a8 stm32g4 -hw/mcu/st/stm32h5xx_hal_driver https://github.com/STMicroelectronics/stm32h5xx_hal_driver.git 2cf77de584196d619cec1b4586c3b9e2820a254e stm32h5 -hw/mcu/st/stm32h7xx_hal_driver https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git d8461b980b59b1625207d8c4f2ce0a9c2a7a3b04 stm32h7 -hw/mcu/st/stm32l0xx_hal_driver https://github.com/STMicroelectronics/stm32l0xx_hal_driver.git fbdacaf6f8c82a4e1eb9bd74ba650b491e97e17b stm32l0 -hw/mcu/st/stm32l1xx_hal_driver https://github.com/STMicroelectronics/stm32l1xx_hal_driver.git 44efc446fa69ed8344e7fd966e68ed11043b35d9 stm32l1 -hw/mcu/st/stm32l4xx_hal_driver https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git aee3d5bf283ae5df87532b781bdd01b7caf256fc stm32l4 -hw/mcu/st/stm32l5xx_hal_driver https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git 675c32a75df37f39d50d61f51cb0dcf53f07e1cb stm32l5 -hw/mcu/st/stm32u5xx_hal_driver https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git 4d93097a67928e9377e655ddd14622adc31b9770 stm32u5 -hw/mcu/st/stm32wbxx_hal_driver https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git 2c5f06638be516c1b772f768456ba637f077bac8 stm32wb -hw/mcu/ti https://github.com/hathach/ti_driver.git 143ed6cc20a7615d042b03b21e070197d473e6e5 msp430 msp432e4 tm4c -hw/mcu/wch/ch32f20x https://github.com/openwch/ch32f20x.git 77c4095087e5ed2c548ec9058e655d0b8757663b ch32f20x -hw/mcu/wch/ch32v103 https://github.com/openwch/ch32v103.git 7578cae0b21f86dd053a1f781b2fc6ab99d0ec17 ch32v10x -hw/mcu/wch/ch32v20x https://github.com/openwch/ch32v20x.git c4c38f507e258a4e69b059ccc2dc27dde33cea1b ch32v20x -hw/mcu/wch/ch32v307 https://github.com/openwch/ch32v307.git 184f21b852cb95eed58e86e901837bc9fff68775 ch32v307 -lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg tm4c -lib/CMSIS_6 https://github.com/ARM-software/CMSIS_6.git b0bbb0423b278ca632cfe1474eb227961d835fd2 ra -lib/FreeRTOS-Kernel https://github.com/FreeRTOS/FreeRTOS-Kernel.git cc0e0707c0c748713485b870bb980852b210877f all -lib/lwip https://github.com/lwip-tcpip/lwip.git 159e31b689577dbf69cf0683bbaffbd71fa5ee10 all -lib/sct_neopixel https://github.com/gsteiert/sct_neopixel.git e73e04ca63495672d955f9268e003cffe168fcd8 lpc55 -tools/uf2 https://github.com/microsoft/uf2.git c594542b2faa01cc33a2b97c9fbebc38549df80a all -======================================== ============================================================== ======================================== ==================================================================================================================================================================================================================================================================================================================================== +======================================== ============================================================== ======================================== ==================================================================================================================================================================================================================================================================================================================================== +Local Path Repo Commit Required by +======================================== ============================================================== ======================================== ==================================================================================================================================================================================================================================================================================================================================== +hw/mcu/allwinner https://github.com/hathach/allwinner_driver.git 8e5e89e8e132c0fd90e72d5422e5d3d68232b756 fc100s +hw/mcu/analog/max32 https://github.com/analogdevicesinc/msdk.git b20b398d3e5e2007594e54a74ba3d2a2e50ddd75 max32650 max32666 max32690 max78002 +hw/mcu/bridgetek/ft9xx/ft90x-sdk https://github.com/BRTSG-FOSS/ft90x-sdk.git 91060164afe239fcb394122e8bf9eb24d3194eb1 brtmm90x +hw/mcu/broadcom https://github.com/adafruit/broadcom-peripherals.git 08370086080759ed54ac1136d62d2ad24c6fa267 broadcom_32bit broadcom_64bit +hw/mcu/gd/nuclei-sdk https://github.com/Nuclei-Software/nuclei-sdk.git 7eb7bfa9ea4fbeacfafe1d5f77d5a0e6ed3922e7 gd32vf103 +hw/mcu/infineon/mtb-xmclib-cat3 https://github.com/Infineon/mtb-xmclib-cat3.git daf5500d03cba23e68c2f241c30af79cd9d63880 xmc4000 +hw/mcu/microchip https://github.com/hathach/microchip_driver.git 9e8b37e307d8404033bb881623a113931e1edf27 sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg +hw/mcu/mindmotion/mm32sdk https://github.com/hathach/mm32sdk.git b93e856211060ae825216c6a1d6aa347ec758843 mm32 +hw/mcu/nordic/nrfx https://github.com/NordicSemiconductor/nrfx.git 7c47cc0a56ce44658e6da2458e86cd8783ccc4a2 nrf +hw/mcu/nuvoton https://github.com/majbthrd/nuc_driver.git 2204191ec76283371419fbcec207da02e1bc22fa nuc +hw/mcu/nxp/lpcopen https://github.com/hathach/nxp_lpcopen.git b41cf930e65c734d8ec6de04f1d57d46787c76ae lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 +hw/mcu/nxp/mcux-sdk https://github.com/hathach/mcux-sdk.git 144f1eb7ea8c06512e12f12b27383601c0272410 kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt +hw/mcu/raspberry_pi/Pico-PIO-USB https://github.com/sekigon-gonnoc/Pico-PIO-USB.git fe9133fc513b82cc3dc62c67cb51f2339cf29ef7 rp2040 +hw/mcu/renesas/fsp https://github.com/renesas/fsp.git edcc97d684b6f716728a60d7a6fea049d9870bd6 ra +hw/mcu/renesas/rx https://github.com/kkitayam/rx_device.git 706b4e0cf485605c32351e2f90f5698267996023 rx +hw/mcu/silabs/cmsis-dfp-efm32gg12b https://github.com/cmsis-packs/cmsis-dfp-efm32gg12b.git f1c31b7887669cb230b3ea63f9b56769078960bc efm32 +hw/mcu/sony/cxd56/spresense-exported-sdk https://github.com/sonydevworld/spresense-exported-sdk.git 2ec2a1538362696118dc3fdf56f33dacaf8f4067 spresense +hw/mcu/st/cmsis_device_c0 https://github.com/STMicroelectronics/cmsis_device_c0.git fb56b1b70c73b74eacda2a4bcc36886444364ab3 stm32c0 +hw/mcu/st/cmsis_device_f0 https://github.com/STMicroelectronics/cmsis_device_f0.git 2fc25ee22264bc27034358be0bd400b893ef837e stm32f0 +hw/mcu/st/cmsis_device_f1 https://github.com/STMicroelectronics/cmsis_device_f1.git 6601104a6397299b7304fd5bcd9a491f56cb23a6 stm32f1 +hw/mcu/st/cmsis_device_f2 https://github.com/STMicroelectronics/cmsis_device_f2.git 182fcb3681ce116816feb41b7764f1b019ce796f stm32f2 +hw/mcu/st/cmsis_device_f3 https://github.com/STMicroelectronics/cmsis_device_f3.git 5e4ee5ed7a7b6c85176bb70a9fd3c72d6eb99f1b stm32f3 +hw/mcu/st/cmsis_device_f4 https://github.com/STMicroelectronics/cmsis_device_f4.git 2615e866fa48fe1ff1af9e31c348813f2b19e7ec stm32f4 +hw/mcu/st/cmsis_device_f7 https://github.com/STMicroelectronics/cmsis_device_f7.git 25b0463439303b7a38f0d27b161f7d2f3c096e79 stm32f7 +hw/mcu/st/cmsis_device_g0 https://github.com/STMicroelectronics/cmsis_device_g0.git 3a23e1224417f3f2d00300ecd620495e363f2094 stm32g0 +hw/mcu/st/cmsis_device_g4 https://github.com/STMicroelectronics/cmsis_device_g4.git ce822adb1dc552b3aedd13621edbc7fdae124878 stm32g4 +hw/mcu/st/cmsis_device_h5 https://github.com/STMicroelectronics/cmsis_device_h5.git cd2d1d579743de57b88ccaf61a968b9c05848ffc stm32h5 +hw/mcu/st/cmsis_device_h7 https://github.com/STMicroelectronics/cmsis_device_h7.git 60dc2c913203dc8629dc233d4384dcc41c91e77f stm32h7 +hw/mcu/st/cmsis_device_h7rs https://github.com/STMicroelectronics/cmsis_device_h7rs.git 832649d1fd09bd901e9f68e979522e5c209ebf20 stm32h7rs +hw/mcu/st/cmsis_device_l0 https://github.com/STMicroelectronics/cmsis_device_l0.git 69cd5999fd40ae6e546d4905b21635c6ca1bcb92 stm32l0 +hw/mcu/st/cmsis_device_l1 https://github.com/STMicroelectronics/cmsis_device_l1.git 7f16ec0a1c4c063f84160b4cc6bf88ad554a823e stm32l1 +hw/mcu/st/cmsis_device_l4 https://github.com/STMicroelectronics/cmsis_device_l4.git 6ca7312fa6a5a460b5a5a63d66da527fdd8359a6 stm32l4 +hw/mcu/st/cmsis_device_l5 https://github.com/STMicroelectronics/cmsis_device_l5.git d922865fc0326a102c26211c44b8e42f52c1e53d stm32l5 +hw/mcu/st/cmsis_device_u5 https://github.com/STMicroelectronics/cmsis_device_u5.git 5ad9797c54ec3e55eff770fc9b3cd4a1aefc1309 stm32u5 +hw/mcu/st/cmsis_device_wb https://github.com/STMicroelectronics/cmsis_device_wb.git 9c5d1920dd9fabbe2548e10561d63db829bb744f stm32wb +hw/mcu/st/stm32-mfxstm32l152 https://github.com/STMicroelectronics/stm32-mfxstm32l152.git 7f4389efee9c6a655b55e5df3fceef5586b35f9b stm32h7 +hw/mcu/st/stm32c0xx_hal_driver https://github.com/STMicroelectronics/stm32c0xx_hal_driver.git 41253e2f1d7ae4a4d0c379cf63f5bcf71fcf8eb3 stm32c0 +hw/mcu/st/stm32f0xx_hal_driver https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git 0e95cd88657030f640a11e690a8a5186c7712ea5 stm32f0 +hw/mcu/st/stm32f1xx_hal_driver https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git 1dd9d3662fb7eb2a7f7d3bc0a4c1dc7537915a29 stm32f1 +hw/mcu/st/stm32f2xx_hal_driver https://github.com/STMicroelectronics/stm32f2xx_hal_driver.git c75ace9b908a9aca631193ebf2466963b8ea33d0 stm32f2 +hw/mcu/st/stm32f3xx_hal_driver https://github.com/STMicroelectronics/stm32f3xx_hal_driver.git 1761b6207318ede021706e75aae78f452d72b6fa stm32f3 +hw/mcu/st/stm32f4xx_hal_driver https://github.com/STMicroelectronics/stm32f4xx_hal_driver.git 04e99fbdabd00ab8f370f377c66b0a4570365b58 stm32f4 +hw/mcu/st/stm32f7xx_hal_driver https://github.com/STMicroelectronics/stm32f7xx_hal_driver.git f7ffdf6bf72110e58b42c632b0a051df5997e4ee stm32f7 +hw/mcu/st/stm32g0xx_hal_driver https://github.com/STMicroelectronics/stm32g0xx_hal_driver.git e911b12c7f67084d7f6b76157a4c0d4e2ec3779c stm32g0 +hw/mcu/st/stm32g4xx_hal_driver https://github.com/STMicroelectronics/stm32g4xx_hal_driver.git 8b4518417706d42eef5c14e56a650005abf478a8 stm32g4 +hw/mcu/st/stm32h5xx_hal_driver https://github.com/STMicroelectronics/stm32h5xx_hal_driver.git 2cf77de584196d619cec1b4586c3b9e2820a254e stm32h5 +hw/mcu/st/stm32h7xx_hal_driver https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git d8461b980b59b1625207d8c4f2ce0a9c2a7a3b04 stm32h7 +hw/mcu/st/stm32h7rsxx_hal_driver https://github.com/STMicroelectronics/stm32h7rsxx_hal_driver.git 7ca2e07ca21bc66b53654e845b4c85c884343b60 stm32h7rs +hw/mcu/st/stm32l0xx_hal_driver https://github.com/STMicroelectronics/stm32l0xx_hal_driver.git fbdacaf6f8c82a4e1eb9bd74ba650b491e97e17b stm32l0 +hw/mcu/st/stm32l1xx_hal_driver https://github.com/STMicroelectronics/stm32l1xx_hal_driver.git 44efc446fa69ed8344e7fd966e68ed11043b35d9 stm32l1 +hw/mcu/st/stm32l4xx_hal_driver https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git aee3d5bf283ae5df87532b781bdd01b7caf256fc stm32l4 +hw/mcu/st/stm32l5xx_hal_driver https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git 675c32a75df37f39d50d61f51cb0dcf53f07e1cb stm32l5 +hw/mcu/st/stm32u5xx_hal_driver https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git 4d93097a67928e9377e655ddd14622adc31b9770 stm32u5 +hw/mcu/st/stm32wbxx_hal_driver https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git 2c5f06638be516c1b772f768456ba637f077bac8 stm32wb +hw/mcu/ti https://github.com/hathach/ti_driver.git 143ed6cc20a7615d042b03b21e070197d473e6e5 msp430 msp432e4 tm4c +hw/mcu/wch/ch32f20x https://github.com/openwch/ch32f20x.git 77c4095087e5ed2c548ec9058e655d0b8757663b ch32f20x +hw/mcu/wch/ch32v103 https://github.com/openwch/ch32v103.git 7578cae0b21f86dd053a1f781b2fc6ab99d0ec17 ch32v10x +hw/mcu/wch/ch32v20x https://github.com/openwch/ch32v20x.git c4c38f507e258a4e69b059ccc2dc27dde33cea1b ch32v20x +hw/mcu/wch/ch32v307 https://github.com/openwch/ch32v307.git 184f21b852cb95eed58e86e901837bc9fff68775 ch32v307 +lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg tm4c +lib/CMSIS_6 https://github.com/ARM-software/CMSIS_6.git b0bbb0423b278ca632cfe1474eb227961d835fd2 ra +lib/FreeRTOS-Kernel https://github.com/FreeRTOS/FreeRTOS-Kernel.git cc0e0707c0c748713485b870bb980852b210877f all +lib/lwip https://github.com/lwip-tcpip/lwip.git 159e31b689577dbf69cf0683bbaffbd71fa5ee10 all +lib/sct_neopixel https://github.com/gsteiert/sct_neopixel.git e73e04ca63495672d955f9268e003cffe168fcd8 lpc55 +tools/uf2 https://github.com/microsoft/uf2.git c594542b2faa01cc33a2b97c9fbebc38549df80a all +======================================== ============================================================== ======================================== ==================================================================================================================================================================================================================================================================================================================================== diff --git a/tools/get_deps.py b/tools/get_deps.py index c8459c1f1..0b49dfd72 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -103,6 +103,9 @@ deps_optional = { 'hw/mcu/st/cmsis_device_h7': ['https://github.com/STMicroelectronics/cmsis_device_h7.git', '60dc2c913203dc8629dc233d4384dcc41c91e77f', 'stm32h7'], + 'hw/mcu/st/cmsis_device_h7rs': ['https://github.com/STMicroelectronics/cmsis_device_h7rs.git', + '832649d1fd09bd901e9f68e979522e5c209ebf20', + 'stm32h7rs'], 'hw/mcu/st/cmsis_device_h5': ['https://github.com/STMicroelectronics/cmsis_device_h5.git', 'cd2d1d579743de57b88ccaf61a968b9c05848ffc', 'stm32h5'], @@ -157,6 +160,9 @@ deps_optional = { 'hw/mcu/st/stm32h7xx_hal_driver': ['https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git', 'd8461b980b59b1625207d8c4f2ce0a9c2a7a3b04', 'stm32h7'], + 'hw/mcu/st/stm32h7rsxx_hal_driver': ['https://github.com/STMicroelectronics/stm32h7rsxx-hal-driver.git', + '7ca2e07ca21bc66b53654e845b4c85c884343b60', + 'stm32h7rs'], 'hw/mcu/st/stm32h5xx_hal_driver': ['https://github.com/STMicroelectronics/stm32h5xx_hal_driver.git', '2cf77de584196d619cec1b4586c3b9e2820a254e', 'stm32h5'], @@ -198,7 +204,7 @@ deps_optional = { 'imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x ' 'lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 ' 'stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 ' - 'stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb ' + 'stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb ' 'sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg ' 'tm4c '], 'lib/CMSIS_6': ['https://github.com/ARM-software/CMSIS_6.git', From f6f20e17abc6c0131da7c82e0bfba0690f30bab2 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 24 Jan 2025 16:54:36 +0100 Subject: [PATCH 044/382] Add NUCLEO-H7S3L8 BSP. Signed-off-by: HiFiPhile --- docs/reference/boards.rst | 1 + hw/bsp/board_mcu.h | 3 + .../stm32h7rs/FreeRTOSConfig/FreeRTOSConfig.h | 149 ++ .../boards/stm32h7s3nucleo/board.cmake | 17 + .../stm32h7rs/boards/stm32h7s3nucleo/board.h | 262 +++ .../stm32h7rs/boards/stm32h7s3nucleo/board.mk | 15 + .../stm32h7s3nucleo/tcpp0203/LICENSE.txt | 6 + .../tcpp0203/Release_Notes.html | 205 ++ .../tcpp0203/_htmresc/favicon.png | Bin 0 -> 4126 bytes .../tcpp0203/_htmresc/mini-st_2020.css | 1703 +++++++++++++++++ .../tcpp0203/_htmresc/st_logo_2020.png | Bin 0 -> 7520 bytes .../stm32h7s3nucleo/tcpp0203/tcpp0203.c | 888 +++++++++ .../stm32h7s3nucleo/tcpp0203/tcpp0203.h | 355 ++++ .../stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c | 75 + .../stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h | 100 + hw/bsp/stm32h7rs/family.c | 313 +++ hw/bsp/stm32h7rs/family.cmake | 150 ++ hw/bsp/stm32h7rs/family.mk | 92 + hw/bsp/stm32h7rs/stm32h7rsxx_hal_conf.h | 501 +++++ src/portable/synopsys/dwc2/dwc2_info.md | 116 +- src/portable/synopsys/dwc2/dwc2_info.py | 1 + 21 files changed, 4894 insertions(+), 58 deletions(-) create mode 100644 hw/bsp/stm32h7rs/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.h create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/Release_Notes.html create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/favicon.png create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/st_logo_2020.png create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h create mode 100644 hw/bsp/stm32h7rs/family.c create mode 100644 hw/bsp/stm32h7rs/family.cmake create mode 100644 hw/bsp/stm32h7rs/family.mk create mode 100644 hw/bsp/stm32h7rs/stm32h7rsxx_hal_conf.h diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 4739467bc..2ee40cf7e 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -261,6 +261,7 @@ stm32h743nucleo STM32 H743 Nucleo stm32h7 https://www.st stm32h745disco STM32 H745 Discovery stm32h7 https://www.st.com/en/evaluation-tools/stm32h745i-disco.html stm32h750_weact STM32 H750 WeAct stm32h7 https://www.adafruit.com/product/5032 stm32h750bdk STM32 H750b Discovery Kit stm32h7 https://www.st.com/en/evaluation-tools/stm32h750b-dk.html +stm32h7s3nucleo STM32 H7S3 Nucleo stm32h7rs https://www.st.com/en/evaluation-tools/nucleo-h7s3l8.html waveshare_openh743i Waveshare Open H743i stm32h7 https://www.waveshare.com/openh743i-c-standard.htm stm32l052dap52 STM32 L052 DAP stm32l0 n/a stm32l0538disco STM32 L0538 Discovery stm32l0 https://www.st.com/en/evaluation-tools/32l0538discovery.html diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h index e720cd747..4613343d4 100644 --- a/hw/bsp/board_mcu.h +++ b/hw/bsp/board_mcu.h @@ -89,6 +89,9 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32H7 #include "stm32h7xx.h" +#elif CFG_TUSB_MCU == OPT_MCU_STM32H7RS + #include "stm32h7rsxx.h" + #elif CFG_TUSB_MCU == OPT_MCU_STM32L0 #include "stm32l0xx.h" diff --git a/hw/bsp/stm32h7rs/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32h7rs/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..9fd3f6c50 --- /dev/null +++ b/hw/bsp/stm32h7rs/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,149 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "stm32h7rsxx.h" +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*8*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 4 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<port, pindef->pin_init.Pin, GPIO_PIN_SET); + + __HAL_RCC_I2C3_CLK_ENABLE(); + __HAL_RCC_I2C3_FORCE_RESET(); + __HAL_RCC_I2C3_RELEASE_RESET(); + if (HAL_I2C_Init(&i2c_handle) != HAL_OK) { + return HAL_ERROR; + } + + NVIC_SetPriority(EXTI8_IRQn, 12); + NVIC_EnableIRQ(EXTI8_IRQn); + + return 0; +} + +int32_t board_tcpp0203_deinit(void) { + return 0; +} + +int32_t i2c_readreg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { + TU_ASSERT (HAL_OK == HAL_I2C_Mem_Read(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000)); + return 0; +} + +int32_t i2c_writereg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { + TU_ASSERT(HAL_OK == HAL_I2C_Mem_Write(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000)); + return 0; +} + +static inline void board_init2(void) { + TCPP0203_IO_t io_ctx; + + io_ctx.Address = TCPP0203_I2C_ADDRESS_X68; + io_ctx.Init = board_tcpp0203_init; + io_ctx.DeInit = board_tcpp0203_deinit; + io_ctx.ReadReg = i2c_readreg; + io_ctx.WriteReg = i2c_writereg; + + TU_ASSERT(TCPP0203_RegisterBusIO(&tcpp0203_obj, &io_ctx) == TCPP0203_OK, ); + + TU_ASSERT(TCPP0203_Init(&tcpp0203_obj) == TCPP0203_OK, ); + + TU_ASSERT(TCPP0203_SetPowerMode(&tcpp0203_obj, TCPP0203_POWER_MODE_NORMAL) == TCPP0203_OK, ); +} + +void board_vbus_set(uint8_t rhport, bool state) { + (void) state; + if (rhport == 1) { + TU_ASSERT(TCPP0203_SetGateDriverProvider(&tcpp0203_obj, TCPP0203_GD_PROVIDER_SWITCH_CLOSED) == TCPP0203_OK, ); + } +} + +void EXTI8_IRQHandler(void) { + __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_8); + if (tcpp0203_obj.IsInitialized) { + TU_ASSERT(TCPP0203_SetPowerMode(&tcpp0203_obj, TCPP0203_POWER_MODE_NORMAL) == TCPP0203_OK, ); + TU_ASSERT(TCPP0203_SetGateDriverProvider(&tcpp0203_obj, TCPP0203_GD_PROVIDER_SWITCH_CLOSED) == TCPP0203_OK, ); + } +} + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk new file mode 100644 index 000000000..164452fb2 --- /dev/null +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk @@ -0,0 +1,15 @@ +MCU_VARIANT = stm32h7s3xx +CFLAGS += -DSTM32H7S3xx + +# For flash-jlink target +JLINK_DEVICE = stm32h7s3xx + +# flash target using on-board stlink +flash: flash-stlink + +SRC_C += \ + $(BOARD_PATH)/tcpp0203/tcpp0203.c \ + $(BOARD_PATH)/tcpp0203/tcpp0203_reg.c \ + +INC += \ + $(BOARD_PATH)/tcpp0203 \ diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt new file mode 100644 index 000000000..3edc4d146 --- /dev/null +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt @@ -0,0 +1,6 @@ +This software component is provided to you as part of a software package and +applicable license terms are in the Package_license file. If you received this +software component outside of a package or without applicable license terms, +the terms of the BSD-3-Clause license shall apply. +You may obtain a copy of the BSD-3-Clause at: +https://opensource.org/licenses/BSD-3-Clause diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/Release_Notes.html b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/Release_Notes.html new file mode 100644 index 000000000..6bbba86a4 --- /dev/null +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/Release_Notes.html @@ -0,0 +1,205 @@ + + + + + + + Release Notes for TCPP0203 Component Driver + + + + + + +
+
+
+

Release Notes for TCPP0203 Component Driver

+

Copyright © 2020 STMicroelectronics
+

+ +
+

Purpose

+

This driver provides a set of functions needed to drive TCPP0203 Type-C Port Protection component

+
+
+

Update History

+
+ +
+

Main Changes

+

Maintenance release

+

Contents

+ + + + + + + + + + + +
Headline
MISRA Rule-81.13 correction on TCPP0203 component driver files
+

Backward compatibility

+

No compatibility break with previous version

+

Dependencies

+
+
+
+ +
+

Main Changes

+

Maintenance release

+

Contents

+ + + + + + + + + + + + +
Fixed bugs list
Headline
MISRA corrections on TCPP0203 component driver files
+

Known Limitations

+

Outstanding bugs list : None

+

Requirements not met or planned in a forthcoming release : None

+

Development Toolchains and Compilers

+
    +
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • +
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • +
  • STM32CubeIDE toolchain V1.8.0
  • +
+

Backward compatibility

+

No compatibility break with previous version

+

Dependencies

+
+
+
+ +
+

Main Changes

+

Maintenance release

+

Contents

+ + + + + + + + + + + + +
Fixed bugs list
Headline
License updates
+

Known Limitations

+

Outstanding bugs list : None

+

Requirements not met or planned in a forthcoming release : None

+

Development Toolchains and Compilers

+
    +
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • +
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • +
  • STM32CubeIDE toolchain V1.6.0
  • +
+

Backward compatibility

+

No compatibility break with previous version

+

Dependencies

+
+
+
+ +
+

Main Changes

+

Maintenance release

+

Contents

+ + + + + + + + + + + + +
Fixed bugs list
Headline
CodeSpell correction on TCPP0203 component driver files
+

Known Limitations

+

Outstanding bugs list : None

+

Requirements not met or planned in a forthcoming release : None

+

Development Toolchains and Compilers

+
    +
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • +
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • +
  • STM32CubeIDE toolchain V1.5.0
  • +
+

Backward compatibility

+

No compatibility break with previous version

+

Dependencies

+
+
+
+ +
+

Main Changes

+

Maintenance release

+

Contents

+ + + + + + + + + + + + +
Fixed bugs list
Headline
MCUAstyle correction on TCPP0203 component driver files
+

Known Limitations

+

Outstanding bugs list : None

+

Requirements not met or planned in a forthcoming release : None

+

Development Toolchains and Compilers

+
    +
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • +
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • +
  • STM32CubeIDE toolchain V1.5.0
  • +
+

Backward compatibility

+

No compatibility break with previous version

+

Dependencies

+
+
+
+ +
+

Main Changes

+
    +
  • First official release of TCPP0203 Type-C port Protection Component drivers
  • +
+
+
+
+
+
+

For complete documentation on STM32,visit: [www.st.com/stm32]

+This release note uses up to date web standards and, for this reason, should not be opened with Internet Explorer but preferably with popular browsers such as Google Chrome, Mozilla Firefox, Opera or Microsoft Edge. +
+ + diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/favicon.png b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..06713eec4974e141c6e9b4156d34e61e89f282ca GIT binary patch literal 4126 zcmV+(5aI8MP)ZIGU@QfPy~$kHP}Vz9c$a)g>fT6hB^OaK4>c|MGS0000HbW%=J|NsC0|NsC0 z|NsC0|NsC0041%NVgLXD!bwCyRCwCllie1CAP9sJ&9ooo{hxLjw5@YC+xxf~%TE}{ zNd5%935b--eKa7{Q8)vZ;eI6pGFH>rL)887WOA={e(b_&0g-g6to#Hm2B3vqWV>1u z@z7*I(bdWdx-Y=OT@|og)oZEgAbc7ep|Gf{$7j1Oa#T&r4>0xv(+}tR_4biWa z1Q-BfcsgeLIJPbT0000rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000F^NklQWRUVq~pvFslpiNq83Yr*1(ELa!!kppKfxQKEkPzz^I>0W)!71xam z(B64`)5a~kHf9SBOp*Wvo{xA*e4|Kv3g6TCo+fF8q^C$|g>#NlXyY$%lmkmCh$x1Z zFbJ_hiDG`37w>KPVB83d7E3>R@-M9$`|}|QFF}1qSk!nanPdVd3K38edo3y+D*=Uo zfOWCwj(F@GSjPG&B<0O;H!Zm0g>eDeK09{b@xB};mEy; z;Gp5H_Cr65qKM1uYIu6x&16!Ei=BHfJLe)1IUnFqc6d#D=ZVQmV9C73vy1=x$SK;s z=*CYZP+Ei1D5Vjl#u88v5dv#jId?iu)8mM}{mD`GcMXtAC5ap?ZoKr&iYuqTKHe$t zTR%R$ZZwxec?l+0r_LIVbe-mzH+D0*ZYsu4BE~~JA2A+AD?BAArO=g8ZfvXtU~o9c zZ(Bd-RFK5jh*DvM1v6^41HB@0K0qn7E8E&Xz1mk6hvmx?*|WB_H!dcO;5R$=<4b~s z5zr3N4zxlkMKOrDeny(PGpEM6^hGyc7lhg>MWtM!af*pn%&q_PxI(n^(-Zd{ICPAp z(WE@Zz5|EZyt{MEDy&l5$Cba^zU!9k&;Vs7lk$@o02LOwb#e2{#3%Cn2>kQF(RKUU z+tW!;FT0@d+TX^L;>@3RytlTP&ts$pqA}TwENBlg9?$-D zF9Sn4URZx8)hVBw<~NY=h3=so7{jEhG%Zc_0QBSvY~K4BS|W5MAem5XSb6m}VDN$f zy+b3n9qjIJoHM5pqYa`IPH9AIoM=!AE1Er>r|3E}#Jq-S)cTrfD&TZjAuN@+V}3mi zlhOce+q<8>Y?i93G=*Z3Web`ri!Q%p%LR*(bB?;|)B`&=J&ab0Z(UKpbzyZV5o*#& z0FLzzaI$v*-#WB)+`n>BoJ*1AwU0XSu;@w&Hu1WYXVR#!8itC%68CzMeiXhL#`9W$9J30NB-Wg!ex`hBlg9F5u@&o4>hd`TWPv z{r{JbyvQGZzbyvPS}zAifbhF49z~X|@9v|!=No>qsF|P~vf=g>7#%0yk<U?Ha8*Z4HW>#8w>z$A3 z>^uQlk;$a-6CQ(uc@RM)Cbss!xuPVl2@c1u-5tEUw}U8OfP_J+QYhfu$B<0Cj3xm7 c?*aZZ00ulYFs-m=@&Et;07*qoM6N<$f~=14i~s-t literal 0 HcmV?d00001 diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css new file mode 100644 index 000000000..3d9e81ad3 --- /dev/null +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css @@ -0,0 +1,1703 @@ +@charset "UTF-8"; +/* + Flavor name: Custom (mini-custom) + Generated online - https://minicss.org/flavors + mini.css version: v3.0.1 +*/ +/* + Browsers resets and base typography. +*/ +/* Core module CSS variable definitions */ +:root { + --fore-color: #03234b; + --secondary-fore-color: #03234b; + --back-color: #ffffff; + --secondary-back-color: #ffffff; + --blockquote-color: #e6007e; + --pre-color: #e6007e; + --border-color: #3cb4e6; + --secondary-border-color: #3cb4e6; + --heading-ratio: 1.2; + --universal-margin: 0.5rem; + --universal-padding: 0.25rem; + --universal-border-radius: 0.075rem; + --background-margin: 1.5%; + --a-link-color: #3cb4e6; + --a-visited-color: #8c0078; } + +html { + font-size: 13.5px; } + +a, b, del, em, i, ins, q, span, strong, u { + font-size: 1em; } + +html, * { + font-family: -apple-system, BlinkMacSystemFont, Helvetica, arial, sans-serif; + line-height: 1.25; + -webkit-text-size-adjust: 100%; } + +* { + font-size: 1rem; } + +body { + margin: 0; + color: var(--fore-color); + @background: var(--back-color); + background: var(--back-color) linear-gradient(#ffd200, #ffd200) repeat-y left top; + background-size: var(--background-margin); + } + +details { + display: block; } + +summary { + display: list-item; } + +abbr[title] { + border-bottom: none; + text-decoration: underline dotted; } + +input { + overflow: visible; } + +img { + max-width: 100%; + height: auto; } + +h1, h2, h3, h4, h5, h6 { + line-height: 1.25; + margin: calc(1.5 * var(--universal-margin)) var(--universal-margin); + font-weight: 400; } + h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { + color: var(--secondary-fore-color); + display: block; + margin-top: -0.25rem; } + +h1 { + font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio)); } + +h2 { + font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) ); + border-style: none none solid none ; + border-width: thin; + border-color: var(--border-color); } +h3 { + font-size: calc(1rem * var(--heading-ratio) ); } + +h4 { + font-size: calc(1rem * var(--heading-ratio)); } + +h5 { + font-size: 1rem; } + +h6 { + font-size: calc(1rem / var(--heading-ratio)); } + +p { + margin: var(--universal-margin); } + +ol, ul { + margin: var(--universal-margin); + padding-left: calc(3 * var(--universal-margin)); } + +b, strong { + font-weight: 700; } + +hr { + box-sizing: content-box; + border: 0; + line-height: 1.25em; + margin: var(--universal-margin); + height: 0.0714285714rem; + background: linear-gradient(to right, transparent, var(--border-color) 20%, var(--border-color) 80%, transparent); } + +blockquote { + display: block; + position: relative; + font-style: italic; + color: var(--secondary-fore-color); + margin: var(--universal-margin); + padding: calc(3 * var(--universal-padding)); + border: 0.0714285714rem solid var(--secondary-border-color); + border-left: 0.3rem solid var(--blockquote-color); + border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } + blockquote:before { + position: absolute; + top: calc(0rem - var(--universal-padding)); + left: 0; + font-family: sans-serif; + font-size: 2rem; + font-weight: 800; + content: "\201c"; + color: var(--blockquote-color); } + blockquote[cite]:after { + font-style: normal; + font-size: 0.75em; + font-weight: 700; + content: "\a— " attr(cite); + white-space: pre; } + +code, kbd, pre, samp { + font-family: Menlo, Consolas, monospace; + font-size: 0.85em; } + +code { + background: var(--secondary-back-color); + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } + +kbd { + background: var(--fore-color); + color: var(--back-color); + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } + +pre { + overflow: auto; + background: var(--secondary-back-color); + padding: calc(1.5 * var(--universal-padding)); + margin: var(--universal-margin); + border: 0.0714285714rem solid var(--secondary-border-color); + border-left: 0.2857142857rem solid var(--pre-color); + border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } + +sup, sub, code, kbd { + line-height: 0; + position: relative; + vertical-align: baseline; } + +small, sup, sub, figcaption { + font-size: 0.75em; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +figure { + margin: var(--universal-margin); } + +figcaption { + color: var(--secondary-fore-color); } + +a { + text-decoration: none; } + a:link { + color: var(--a-link-color); } + a:visited { + color: var(--a-visited-color); } + a:hover, a:focus { + text-decoration: underline; } + +/* + Definitions for the grid system, cards and containers. +*/ +.container { + margin: 0 auto; + padding: 0 calc(1.5 * var(--universal-padding)); } + +.row { + box-sizing: border-box; + display: flex; + flex: 0 1 auto; + flex-flow: row wrap; + margin: 0 0 0 var(--background-margin); } + +.col-sm, +[class^='col-sm-'], +[class^='col-sm-offset-'], +.row[class*='cols-sm-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + +.col-sm, +.row.cols-sm > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + +.col-sm-1, +.row.cols-sm-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + +.col-sm-offset-0 { + margin-left: 0; } + +.col-sm-2, +.row.cols-sm-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + +.col-sm-offset-1 { + margin-left: 8.3333333333%; } + +.col-sm-3, +.row.cols-sm-3 > * { + max-width: 25%; + flex-basis: 25%; } + +.col-sm-offset-2 { + margin-left: 16.6666666667%; } + +.col-sm-4, +.row.cols-sm-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + +.col-sm-offset-3 { + margin-left: 25%; } + +.col-sm-5, +.row.cols-sm-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + +.col-sm-offset-4 { + margin-left: 33.3333333333%; } + +.col-sm-6, +.row.cols-sm-6 > * { + max-width: 50%; + flex-basis: 50%; } + +.col-sm-offset-5 { + margin-left: 41.6666666667%; } + +.col-sm-7, +.row.cols-sm-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + +.col-sm-offset-6 { + margin-left: 50%; } + +.col-sm-8, +.row.cols-sm-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + +.col-sm-offset-7 { + margin-left: 58.3333333333%; } + +.col-sm-9, +.row.cols-sm-9 > * { + max-width: 75%; + flex-basis: 75%; } + +.col-sm-offset-8 { + margin-left: 66.6666666667%; } + +.col-sm-10, +.row.cols-sm-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + +.col-sm-offset-9 { + margin-left: 75%; } + +.col-sm-11, +.row.cols-sm-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + +.col-sm-offset-10 { + margin-left: 83.3333333333%; } + +.col-sm-12, +.row.cols-sm-12 > * { + max-width: 100%; + flex-basis: 100%; } + +.col-sm-offset-11 { + margin-left: 91.6666666667%; } + +.col-sm-normal { + order: initial; } + +.col-sm-first { + order: -999; } + +.col-sm-last { + order: 999; } + +@media screen and (min-width: 500px) { + .col-md, + [class^='col-md-'], + [class^='col-md-offset-'], + .row[class*='cols-md-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + + .col-md, + .row.cols-md > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + + .col-md-1, + .row.cols-md-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + + .col-md-offset-0 { + margin-left: 0; } + + .col-md-2, + .row.cols-md-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + + .col-md-offset-1 { + margin-left: 8.3333333333%; } + + .col-md-3, + .row.cols-md-3 > * { + max-width: 25%; + flex-basis: 25%; } + + .col-md-offset-2 { + margin-left: 16.6666666667%; } + + .col-md-4, + .row.cols-md-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + + .col-md-offset-3 { + margin-left: 25%; } + + .col-md-5, + .row.cols-md-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + + .col-md-offset-4 { + margin-left: 33.3333333333%; } + + .col-md-6, + .row.cols-md-6 > * { + max-width: 50%; + flex-basis: 50%; } + + .col-md-offset-5 { + margin-left: 41.6666666667%; } + + .col-md-7, + .row.cols-md-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + + .col-md-offset-6 { + margin-left: 50%; } + + .col-md-8, + .row.cols-md-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + + .col-md-offset-7 { + margin-left: 58.3333333333%; } + + .col-md-9, + .row.cols-md-9 > * { + max-width: 75%; + flex-basis: 75%; } + + .col-md-offset-8 { + margin-left: 66.6666666667%; } + + .col-md-10, + .row.cols-md-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + + .col-md-offset-9 { + margin-left: 75%; } + + .col-md-11, + .row.cols-md-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + + .col-md-offset-10 { + margin-left: 83.3333333333%; } + + .col-md-12, + .row.cols-md-12 > * { + max-width: 100%; + flex-basis: 100%; } + + .col-md-offset-11 { + margin-left: 91.6666666667%; } + + .col-md-normal { + order: initial; } + + .col-md-first { + order: -999; } + + .col-md-last { + order: 999; } } +@media screen and (min-width: 1280px) { + .col-lg, + [class^='col-lg-'], + [class^='col-lg-offset-'], + .row[class*='cols-lg-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + + .col-lg, + .row.cols-lg > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + + .col-lg-1, + .row.cols-lg-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + + .col-lg-offset-0 { + margin-left: 0; } + + .col-lg-2, + .row.cols-lg-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + + .col-lg-offset-1 { + margin-left: 8.3333333333%; } + + .col-lg-3, + .row.cols-lg-3 > * { + max-width: 25%; + flex-basis: 25%; } + + .col-lg-offset-2 { + margin-left: 16.6666666667%; } + + .col-lg-4, + .row.cols-lg-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + + .col-lg-offset-3 { + margin-left: 25%; } + + .col-lg-5, + .row.cols-lg-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + + .col-lg-offset-4 { + margin-left: 33.3333333333%; } + + .col-lg-6, + .row.cols-lg-6 > * { + max-width: 50%; + flex-basis: 50%; } + + .col-lg-offset-5 { + margin-left: 41.6666666667%; } + + .col-lg-7, + .row.cols-lg-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + + .col-lg-offset-6 { + margin-left: 50%; } + + .col-lg-8, + .row.cols-lg-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + + .col-lg-offset-7 { + margin-left: 58.3333333333%; } + + .col-lg-9, + .row.cols-lg-9 > * { + max-width: 75%; + flex-basis: 75%; } + + .col-lg-offset-8 { + margin-left: 66.6666666667%; } + + .col-lg-10, + .row.cols-lg-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + + .col-lg-offset-9 { + margin-left: 75%; } + + .col-lg-11, + .row.cols-lg-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + + .col-lg-offset-10 { + margin-left: 83.3333333333%; } + + .col-lg-12, + .row.cols-lg-12 > * { + max-width: 100%; + flex-basis: 100%; } + + .col-lg-offset-11 { + margin-left: 91.6666666667%; } + + .col-lg-normal { + order: initial; } + + .col-lg-first { + order: -999; } + + .col-lg-last { + order: 999; } } +/* Card component CSS variable definitions */ +:root { + --card-back-color: #3cb4e6; + --card-fore-color: #03234b; + --card-border-color: #03234b; } + +.card { + display: flex; + flex-direction: column; + justify-content: space-between; + align-self: center; + position: relative; + width: 100%; + background: var(--card-back-color); + color: var(--card-fore-color); + border: 0.0714285714rem solid var(--card-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); + overflow: hidden; } + @media screen and (min-width: 320px) { + .card { + max-width: 320px; } } + .card > .sectione { + background: var(--card-back-color); + color: var(--card-fore-color); + box-sizing: border-box; + margin: 0; + border: 0; + border-radius: 0; + border-bottom: 0.0714285714rem solid var(--card-border-color); + padding: var(--universal-padding); + width: 100%; } + .card > .sectione.media { + height: 200px; + padding: 0; + -o-object-fit: cover; + object-fit: cover; } + .card > .sectione:last-child { + border-bottom: 0; } + +/* + Custom elements for card elements. +*/ +@media screen and (min-width: 240px) { + .card.small { + max-width: 240px; } } +@media screen and (min-width: 480px) { + .card.large { + max-width: 480px; } } +.card.fluid { + max-width: 100%; + width: auto; } + +.card.warning { + --card-back-color: #e5b8b7; + --card-fore-color: #3b234b; + --card-border-color: #8c0078; } + +.card.error { + --card-back-color: #464650; + --card-fore-color: #ffffff; + --card-border-color: #8c0078; } + +.card > .sectione.dark { + --card-back-color: #3b234b; + --card-fore-color: #ffffff; } + +.card > .sectione.double-padded { + padding: calc(1.5 * var(--universal-padding)); } + +/* + Definitions for forms and input elements. +*/ +/* Input_control module CSS variable definitions */ +:root { + --form-back-color: #ffe97f; + --form-fore-color: #03234b; + --form-border-color: #3cb4e6; + --input-back-color: #ffffff; + --input-fore-color: #03234b; + --input-border-color: #3cb4e6; + --input-focus-color: #0288d1; + --input-invalid-color: #d32f2f; + --button-back-color: #e2e2e2; + --button-hover-back-color: #dcdcdc; + --button-fore-color: #212121; + --button-border-color: transparent; + --button-hover-border-color: transparent; + --button-group-border-color: rgba(124, 124, 124, 0.54); } + +form { + background: var(--form-back-color); + color: var(--form-fore-color); + border: 0.0714285714rem solid var(--form-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); + padding: calc(2 * var(--universal-padding)) var(--universal-padding); } + +fieldset { + border: 0.0714285714rem solid var(--form-border-color); + border-radius: var(--universal-border-radius); + margin: calc(var(--universal-margin) / 4); + padding: var(--universal-padding); } + +legend { + box-sizing: border-box; + display: table; + max-width: 100%; + white-space: normal; + font-weight: 500; + padding: calc(var(--universal-padding) / 2); } + +label { + padding: calc(var(--universal-padding) / 2) var(--universal-padding); } + +.input-group { + display: inline-block; } + .input-group.fluid { + display: flex; + align-items: center; + justify-content: center; } + .input-group.fluid > input { + max-width: 100%; + flex-grow: 1; + flex-basis: 0px; } + @media screen and (max-width: 499px) { + .input-group.fluid { + align-items: stretch; + flex-direction: column; } } + .input-group.vertical { + display: flex; + align-items: stretch; + flex-direction: column; } + .input-group.vertical > input { + max-width: 100%; + flex-grow: 1; + flex-basis: 0px; } + +[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { + height: auto; } + +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; } + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +input:not([type]), [type="text"], [type="email"], [type="number"], [type="search"], +[type="password"], [type="url"], [type="tel"], [type="checkbox"], [type="radio"], textarea, select { + box-sizing: border-box; + background: var(--input-back-color); + color: var(--input-fore-color); + border: 0.0714285714rem solid var(--input-border-color); + border-radius: var(--universal-border-radius); + margin: calc(var(--universal-margin) / 2); + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } + +input:not([type="button"]):not([type="submit"]):not([type="reset"]):hover, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus, textarea:hover, textarea:focus, select:hover, select:focus { + border-color: var(--input-focus-color); + box-shadow: none; } +input:not([type="button"]):not([type="submit"]):not([type="reset"]):invalid, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus:invalid, textarea:invalid, textarea:focus:invalid, select:invalid, select:focus:invalid { + border-color: var(--input-invalid-color); + box-shadow: none; } +input:not([type="button"]):not([type="submit"]):not([type="reset"])[readonly], textarea[readonly], select[readonly] { + background: var(--secondary-back-color); } + +select { + max-width: 100%; } + +option { + overflow: hidden; + text-overflow: ellipsis; } + +[type="checkbox"], [type="radio"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + position: relative; + height: calc(1rem + var(--universal-padding) / 2); + width: calc(1rem + var(--universal-padding) / 2); + vertical-align: text-bottom; + padding: 0; + flex-basis: calc(1rem + var(--universal-padding) / 2) !important; + flex-grow: 0 !important; } + [type="checkbox"]:checked:before, [type="radio"]:checked:before { + position: absolute; } + +[type="checkbox"]:checked:before { + content: '\2713'; + font-family: sans-serif; + font-size: calc(1rem + var(--universal-padding) / 2); + top: calc(0rem - var(--universal-padding)); + left: calc(var(--universal-padding) / 4); } + +[type="radio"] { + border-radius: 100%; } + [type="radio"]:checked:before { + border-radius: 100%; + content: ''; + top: calc(0.0714285714rem + var(--universal-padding) / 2); + left: calc(0.0714285714rem + var(--universal-padding) / 2); + background: var(--input-fore-color); + width: 0.5rem; + height: 0.5rem; } + +:placeholder-shown { + color: var(--input-fore-color); } + +::-ms-placeholder { + color: var(--input-fore-color); + opacity: 0.54; } + +button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; } + +button, html [type="button"], [type="reset"], [type="submit"] { + -webkit-appearance: button; } + +button { + overflow: visible; + text-transform: none; } + +button, [type="button"], [type="submit"], [type="reset"], +a.button, label.button, .button, +a[role="button"], label[role="button"], [role="button"] { + display: inline-block; + background: var(--button-back-color); + color: var(--button-fore-color); + border: 0.0714285714rem solid var(--button-border-color); + border-radius: var(--universal-border-radius); + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); + margin: var(--universal-margin); + text-decoration: none; + cursor: pointer; + transition: background 0.3s; } + button:hover, button:focus, [type="button"]:hover, [type="button"]:focus, [type="submit"]:hover, [type="submit"]:focus, [type="reset"]:hover, [type="reset"]:focus, + a.button:hover, + a.button:focus, label.button:hover, label.button:focus, .button:hover, .button:focus, + a[role="button"]:hover, + a[role="button"]:focus, label[role="button"]:hover, label[role="button"]:focus, [role="button"]:hover, [role="button"]:focus { + background: var(--button-hover-back-color); + border-color: var(--button-hover-border-color); } + +input:disabled, input[disabled], textarea:disabled, textarea[disabled], select:disabled, select[disabled], button:disabled, button[disabled], .button:disabled, .button[disabled], [role="button"]:disabled, [role="button"][disabled] { + cursor: not-allowed; + opacity: 0.75; } + +.button-group { + display: flex; + border: 0.0714285714rem solid var(--button-group-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); } + .button-group > button, .button-group [type="button"], .button-group > [type="submit"], .button-group > [type="reset"], .button-group > .button, .button-group > [role="button"] { + margin: 0; + max-width: 100%; + flex: 1 1 auto; + text-align: center; + border: 0; + border-radius: 0; + box-shadow: none; } + .button-group > :not(:first-child) { + border-left: 0.0714285714rem solid var(--button-group-border-color); } + @media screen and (max-width: 499px) { + .button-group { + flex-direction: column; } + .button-group > :not(:first-child) { + border: 0; + border-top: 0.0714285714rem solid var(--button-group-border-color); } } + +/* + Custom elements for forms and input elements. +*/ +button.primary, [type="button"].primary, [type="submit"].primary, [type="reset"].primary, .button.primary, [role="button"].primary { + --button-back-color: #1976d2; + --button-fore-color: #f8f8f8; } + button.primary:hover, button.primary:focus, [type="button"].primary:hover, [type="button"].primary:focus, [type="submit"].primary:hover, [type="submit"].primary:focus, [type="reset"].primary:hover, [type="reset"].primary:focus, .button.primary:hover, .button.primary:focus, [role="button"].primary:hover, [role="button"].primary:focus { + --button-hover-back-color: #1565c0; } + +button.secondary, [type="button"].secondary, [type="submit"].secondary, [type="reset"].secondary, .button.secondary, [role="button"].secondary { + --button-back-color: #d32f2f; + --button-fore-color: #f8f8f8; } + button.secondary:hover, button.secondary:focus, [type="button"].secondary:hover, [type="button"].secondary:focus, [type="submit"].secondary:hover, [type="submit"].secondary:focus, [type="reset"].secondary:hover, [type="reset"].secondary:focus, .button.secondary:hover, .button.secondary:focus, [role="button"].secondary:hover, [role="button"].secondary:focus { + --button-hover-back-color: #c62828; } + +button.tertiary, [type="button"].tertiary, [type="submit"].tertiary, [type="reset"].tertiary, .button.tertiary, [role="button"].tertiary { + --button-back-color: #308732; + --button-fore-color: #f8f8f8; } + button.tertiary:hover, button.tertiary:focus, [type="button"].tertiary:hover, [type="button"].tertiary:focus, [type="submit"].tertiary:hover, [type="submit"].tertiary:focus, [type="reset"].tertiary:hover, [type="reset"].tertiary:focus, .button.tertiary:hover, .button.tertiary:focus, [role="button"].tertiary:hover, [role="button"].tertiary:focus { + --button-hover-back-color: #277529; } + +button.inverse, [type="button"].inverse, [type="submit"].inverse, [type="reset"].inverse, .button.inverse, [role="button"].inverse { + --button-back-color: #212121; + --button-fore-color: #f8f8f8; } + button.inverse:hover, button.inverse:focus, [type="button"].inverse:hover, [type="button"].inverse:focus, [type="submit"].inverse:hover, [type="submit"].inverse:focus, [type="reset"].inverse:hover, [type="reset"].inverse:focus, .button.inverse:hover, .button.inverse:focus, [role="button"].inverse:hover, [role="button"].inverse:focus { + --button-hover-back-color: #111; } + +button.small, [type="button"].small, [type="submit"].small, [type="reset"].small, .button.small, [role="button"].small { + padding: calc(0.5 * var(--universal-padding)) calc(0.75 * var(--universal-padding)); + margin: var(--universal-margin); } + +button.large, [type="button"].large, [type="submit"].large, [type="reset"].large, .button.large, [role="button"].large { + padding: calc(1.5 * var(--universal-padding)) calc(2 * var(--universal-padding)); + margin: var(--universal-margin); } + +/* + Definitions for navigation elements. +*/ +/* Navigation module CSS variable definitions */ +:root { + --header-back-color: #03234b; + --header-hover-back-color: #ffd200; + --header-fore-color: #ffffff; + --header-border-color: #3cb4e6; + --nav-back-color: #ffffff; + --nav-hover-back-color: #ffe97f; + --nav-fore-color: #e6007e; + --nav-border-color: #3cb4e6; + --nav-link-color: #3cb4e6; + --footer-fore-color: #ffffff; + --footer-back-color: #03234b; + --footer-border-color: #3cb4e6; + --footer-link-color: #3cb4e6; + --drawer-back-color: #ffffff; + --drawer-hover-back-color: #ffe97f; + --drawer-border-color: #3cb4e6; + --drawer-close-color: #e6007e; } + +header { + height: 2.75rem; + background: var(--header-back-color); + color: var(--header-fore-color); + border-bottom: 0.0714285714rem solid var(--header-border-color); + padding: calc(var(--universal-padding) / 4) 0; + white-space: nowrap; + overflow-x: auto; + overflow-y: hidden; } + header.row { + box-sizing: content-box; } + header .logo { + color: var(--header-fore-color); + font-size: 1.75rem; + padding: var(--universal-padding) calc(2 * var(--universal-padding)); + text-decoration: none; } + header button, header [type="button"], header .button, header [role="button"] { + box-sizing: border-box; + position: relative; + top: calc(0rem - var(--universal-padding) / 4); + height: calc(3.1875rem + var(--universal-padding) / 2); + background: var(--header-back-color); + line-height: calc(3.1875rem - var(--universal-padding) * 1.5); + text-align: center; + color: var(--header-fore-color); + border: 0; + border-radius: 0; + margin: 0; + text-transform: uppercase; } + header button:hover, header button:focus, header [type="button"]:hover, header [type="button"]:focus, header .button:hover, header .button:focus, header [role="button"]:hover, header [role="button"]:focus { + background: var(--header-hover-back-color); } + +nav { + background: var(--nav-back-color); + color: var(--nav-fore-color); + border: 0.0714285714rem solid var(--nav-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); } + nav * { + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } + nav a, nav a:visited { + display: block; + color: var(--nav-link-color); + border-radius: var(--universal-border-radius); + transition: background 0.3s; } + nav a:hover, nav a:focus, nav a:visited:hover, nav a:visited:focus { + text-decoration: none; + background: var(--nav-hover-back-color); } + nav .sublink-1 { + position: relative; + margin-left: calc(2 * var(--universal-padding)); } + nav .sublink-1:before { + position: absolute; + left: calc(var(--universal-padding) - 1 * var(--universal-padding)); + top: -0.0714285714rem; + content: ''; + height: 100%; + border: 0.0714285714rem solid var(--nav-border-color); + border-left: 0; } + nav .sublink-2 { + position: relative; + margin-left: calc(4 * var(--universal-padding)); } + nav .sublink-2:before { + position: absolute; + left: calc(var(--universal-padding) - 3 * var(--universal-padding)); + top: -0.0714285714rem; + content: ''; + height: 100%; + border: 0.0714285714rem solid var(--nav-border-color); + border-left: 0; } + +footer { + background: var(--footer-back-color); + color: var(--footer-fore-color); + border-top: 0.0714285714rem solid var(--footer-border-color); + padding: calc(2 * var(--universal-padding)) var(--universal-padding); + font-size: 0.875rem; } + footer a, footer a:visited { + color: var(--footer-link-color); } + +header.sticky { + position: -webkit-sticky; + position: sticky; + z-index: 1101; + top: 0; } + +footer.sticky { + position: -webkit-sticky; + position: sticky; + z-index: 1101; + bottom: 0; } + +.drawer-toggle:before { + display: inline-block; + position: relative; + vertical-align: bottom; + content: '\00a0\2261\00a0'; + font-family: sans-serif; + font-size: 1.5em; } +@media screen and (min-width: 500px) { + .drawer-toggle:not(.persistent) { + display: none; } } + +[type="checkbox"].drawer { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + [type="checkbox"].drawer + * { + display: block; + box-sizing: border-box; + position: fixed; + top: 0; + width: 320px; + height: 100vh; + overflow-y: auto; + background: var(--drawer-back-color); + border: 0.0714285714rem solid var(--drawer-border-color); + border-radius: 0; + margin: 0; + z-index: 1110; + right: -320px; + transition: right 0.3s; } + [type="checkbox"].drawer + * .drawer-close { + position: absolute; + top: var(--universal-margin); + right: var(--universal-margin); + z-index: 1111; + width: 2rem; + height: 2rem; + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + margin: 0; + cursor: pointer; + transition: background 0.3s; } + [type="checkbox"].drawer + * .drawer-close:before { + display: block; + content: '\00D7'; + color: var(--drawer-close-color); + position: relative; + font-family: sans-serif; + font-size: 2rem; + line-height: 1; + text-align: center; } + [type="checkbox"].drawer + * .drawer-close:hover, [type="checkbox"].drawer + * .drawer-close:focus { + background: var(--drawer-hover-back-color); } + @media screen and (max-width: 320px) { + [type="checkbox"].drawer + * { + width: 100%; } } + [type="checkbox"].drawer:checked + * { + right: 0; } + @media screen and (min-width: 500px) { + [type="checkbox"].drawer:not(.persistent) + * { + position: static; + height: 100%; + z-index: 1100; } + [type="checkbox"].drawer:not(.persistent) + * .drawer-close { + display: none; } } + +/* + Definitions for the responsive table component. +*/ +/* Table module CSS variable definitions. */ +:root { + --table-border-color: #03234b; + --table-border-separator-color: #03234b; + --table-head-back-color: #03234b; + --table-head-fore-color: #ffffff; + --table-body-back-color: #ffffff; + --table-body-fore-color: #03234b; + --table-body-alt-back-color: #f4f4f4; } + +table { + border-collapse: separate; + border-spacing: 0; + margin: 0; + display: flex; + flex: 0 1 auto; + flex-flow: row wrap; + padding: var(--universal-padding); + padding-top: 0; } + table caption { + font-size: 1rem; + margin: calc(2 * var(--universal-margin)) 0; + max-width: 100%; + flex: 0 0 100%; } + table thead, table tbody { + display: flex; + flex-flow: row wrap; + border: 0.0714285714rem solid var(--table-border-color); } + table thead { + z-index: 999; + border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; + border-bottom: 0.0714285714rem solid var(--table-border-separator-color); } + table tbody { + border-top: 0; + margin-top: calc(0 - var(--universal-margin)); + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + table tr { + display: flex; + padding: 0; } + table th, table td { + padding: calc(0.5 * var(--universal-padding)); + font-size: 0.9rem; } + table th { + text-align: left; + background: var(--table-head-back-color); + color: var(--table-head-fore-color); } + table td { + background: var(--table-body-back-color); + color: var(--table-body-fore-color); + border-top: 0.0714285714rem solid var(--table-border-color); } + +table:not(.horizontal) { + overflow: auto; + max-height: 100%; } + table:not(.horizontal) thead, table:not(.horizontal) tbody { + max-width: 100%; + flex: 0 0 100%; } + table:not(.horizontal) tr { + flex-flow: row wrap; + flex: 0 0 100%; } + table:not(.horizontal) th, table:not(.horizontal) td { + flex: 1 0 0%; + overflow: hidden; + text-overflow: ellipsis; } + table:not(.horizontal) thead { + position: sticky; + top: 0; } + table:not(.horizontal) tbody tr:first-child td { + border-top: 0; } + +table.horizontal { + border: 0; } + table.horizontal thead, table.horizontal tbody { + border: 0; + flex: .2 0 0; + flex-flow: row nowrap; } + table.horizontal tbody { + overflow: auto; + justify-content: space-between; + flex: .8 0 0; + margin-left: 0; + padding-bottom: calc(var(--universal-padding) / 4); } + table.horizontal tr { + flex-direction: column; + flex: 1 0 auto; } + table.horizontal th, table.horizontal td { + width: auto; + border: 0; + border-bottom: 0.0714285714rem solid var(--table-border-color); } + table.horizontal th:not(:first-child), table.horizontal td:not(:first-child) { + border-top: 0; } + table.horizontal th { + text-align: right; + border-left: 0.0714285714rem solid var(--table-border-color); + border-right: 0.0714285714rem solid var(--table-border-separator-color); } + table.horizontal thead tr:first-child { + padding-left: 0; } + table.horizontal th:first-child, table.horizontal td:first-child { + border-top: 0.0714285714rem solid var(--table-border-color); } + table.horizontal tbody tr:last-child td { + border-right: 0.0714285714rem solid var(--table-border-color); } + table.horizontal tbody tr:last-child td:first-child { + border-top-right-radius: 0.25rem; } + table.horizontal tbody tr:last-child td:last-child { + border-bottom-right-radius: 0.25rem; } + table.horizontal thead tr:first-child th:first-child { + border-top-left-radius: 0.25rem; } + table.horizontal thead tr:first-child th:last-child { + border-bottom-left-radius: 0.25rem; } + +@media screen and (max-width: 499px) { + table, table.horizontal { + border-collapse: collapse; + border: 0; + width: 100%; + display: table; } + table thead, table th, table.horizontal thead, table.horizontal th { + border: 0; + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + table tbody, table.horizontal tbody { + border: 0; + display: table-row-group; } + table tr, table.horizontal tr { + display: block; + border: 0.0714285714rem solid var(--table-border-color); + border-radius: var(--universal-border-radius); + background: #ffffff; + padding: var(--universal-padding); + margin: var(--universal-margin); + margin-bottom: calc(1 * var(--universal-margin)); } + table th, table td, table.horizontal th, table.horizontal td { + width: auto; } + table td, table.horizontal td { + display: block; + border: 0; + text-align: right; } + table td:before, table.horizontal td:before { + content: attr(data-label); + float: left; + font-weight: 600; } + table th:first-child, table td:first-child, table.horizontal th:first-child, table.horizontal td:first-child { + border-top: 0; } + table tbody tr:last-child td, table.horizontal tbody tr:last-child td { + border-right: 0; } } +table tr:nth-of-type(2n) > td { + background: var(--table-body-alt-back-color); } + +@media screen and (max-width: 500px) { + table tr:nth-of-type(2n) { + background: var(--table-body-alt-back-color); } } +:root { + --table-body-hover-back-color: #90caf9; } + +table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { + background: var(--table-body-hover-back-color); } + +@media screen and (max-width: 500px) { + table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { + background: var(--table-body-hover-back-color); } } +/* + Definitions for contextual background elements, toasts and tooltips. +*/ +/* Contextual module CSS variable definitions */ +:root { + --mark-back-color: #3cb4e6; + --mark-fore-color: #ffffff; } + +mark { + background: var(--mark-back-color); + color: var(--mark-fore-color); + font-size: 0.95em; + line-height: 1em; + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) var(--universal-padding); } + mark.inline-block { + display: inline-block; + font-size: 1em; + line-height: 1.4; + padding: calc(var(--universal-padding) / 2) var(--universal-padding); } + +:root { + --toast-back-color: #424242; + --toast-fore-color: #fafafa; } + +.toast { + position: fixed; + bottom: calc(var(--universal-margin) * 3); + left: 50%; + transform: translate(-50%, -50%); + z-index: 1111; + color: var(--toast-fore-color); + background: var(--toast-back-color); + border-radius: calc(var(--universal-border-radius) * 16); + padding: var(--universal-padding) calc(var(--universal-padding) * 3); } + +:root { + --tooltip-back-color: #212121; + --tooltip-fore-color: #fafafa; } + +.tooltip { + position: relative; + display: inline-block; } + .tooltip:before, .tooltip:after { + position: absolute; + opacity: 0; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + transition: all 0.3s; + z-index: 1010; + left: 50%; } + .tooltip:not(.bottom):before, .tooltip:not(.bottom):after { + bottom: 75%; } + .tooltip.bottom:before, .tooltip.bottom:after { + top: 75%; } + .tooltip:hover:before, .tooltip:hover:after, .tooltip:focus:before, .tooltip:focus:after { + opacity: 1; + clip: auto; + -webkit-clip-path: inset(0%); + clip-path: inset(0%); } + .tooltip:before { + content: ''; + background: transparent; + border: var(--universal-margin) solid transparent; + left: calc(50% - var(--universal-margin)); } + .tooltip:not(.bottom):before { + border-top-color: #212121; } + .tooltip.bottom:before { + border-bottom-color: #212121; } + .tooltip:after { + content: attr(aria-label); + color: var(--tooltip-fore-color); + background: var(--tooltip-back-color); + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + white-space: nowrap; + transform: translateX(-50%); } + .tooltip:not(.bottom):after { + margin-bottom: calc(2 * var(--universal-margin)); } + .tooltip.bottom:after { + margin-top: calc(2 * var(--universal-margin)); } + +:root { + --modal-overlay-color: rgba(0, 0, 0, 0.45); + --modal-close-color: #e6007e; + --modal-close-hover-color: #ffe97f; } + +[type="checkbox"].modal { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + [type="checkbox"].modal + div { + position: fixed; + top: 0; + left: 0; + display: none; + width: 100vw; + height: 100vh; + background: var(--modal-overlay-color); } + [type="checkbox"].modal + div .card { + margin: 0 auto; + max-height: 50vh; + overflow: auto; } + [type="checkbox"].modal + div .card .modal-close { + position: absolute; + top: 0; + right: 0; + width: 1.75rem; + height: 1.75rem; + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + margin: 0; + cursor: pointer; + transition: background 0.3s; } + [type="checkbox"].modal + div .card .modal-close:before { + display: block; + content: '\00D7'; + color: var(--modal-close-color); + position: relative; + font-family: sans-serif; + font-size: 1.75rem; + line-height: 1; + text-align: center; } + [type="checkbox"].modal + div .card .modal-close:hover, [type="checkbox"].modal + div .card .modal-close:focus { + background: var(--modal-close-hover-color); } + [type="checkbox"].modal:checked + div { + display: flex; + flex: 0 1 auto; + z-index: 1200; } + [type="checkbox"].modal:checked + div .card .modal-close { + z-index: 1211; } + +:root { + --collapse-label-back-color: #03234b; + --collapse-label-fore-color: #ffffff; + --collapse-label-hover-back-color: #3cb4e6; + --collapse-selected-label-back-color: #3cb4e6; + --collapse-border-color: var(--collapse-label-back-color); + --collapse-selected-border-color: #ceecf8; + --collapse-content-back-color: #ffffff; + --collapse-selected-label-border-color: #3cb4e6; } + +.collapse { + width: calc(100% - 2 * var(--universal-margin)); + opacity: 1; + display: flex; + flex-direction: column; + margin: var(--universal-margin); + border-radius: var(--universal-border-radius); } + .collapse > [type="radio"], .collapse > [type="checkbox"] { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + .collapse > label { + flex-grow: 1; + display: inline-block; + height: 1.25rem; + cursor: pointer; + transition: background 0.2s; + color: var(--collapse-label-fore-color); + background: var(--collapse-label-back-color); + border: 0.0714285714rem solid var(--collapse-selected-border-color); + padding: calc(1.25 * var(--universal-padding)); } + .collapse > label:hover, .collapse > label:focus { + background: var(--collapse-label-hover-back-color); } + .collapse > label + div { + flex-basis: auto; + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + transition: max-height 0.3s; + max-height: 1px; } + .collapse > :checked + label { + background: var(--collapse-selected-label-back-color); + border-color: var(--collapse-selected-label-border-color); } + .collapse > :checked + label + div { + box-sizing: border-box; + position: relative; + width: 100%; + height: auto; + overflow: auto; + margin: 0; + background: var(--collapse-content-back-color); + border: 0.0714285714rem solid var(--collapse-selected-border-color); + border-top: 0; + padding: var(--universal-padding); + clip: auto; + -webkit-clip-path: inset(0%); + clip-path: inset(0%); + max-height: 100%; } + .collapse > label:not(:first-of-type) { + border-top: 0; } + .collapse > label:first-of-type { + border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; } + .collapse > label:last-of-type:not(:first-of-type) { + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + .collapse > label:last-of-type:first-of-type { + border-radius: var(--universal-border-radius); } + .collapse > :checked:last-of-type:not(:first-of-type) + label { + border-radius: 0; } + .collapse > :checked:last-of-type + label + div { + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + +/* + Custom elements for contextual background elements, toasts and tooltips. +*/ +mark.tertiary { + --mark-back-color: #3cb4e6; } + +mark.tag { + padding: calc(var(--universal-padding)/2) var(--universal-padding); + border-radius: 1em; } + +/* + Definitions for progress elements and spinners. +*/ +/* Progress module CSS variable definitions */ +:root { + --progress-back-color: #3cb4e6; + --progress-fore-color: #555; } + +progress { + display: block; + vertical-align: baseline; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 0.75rem; + width: calc(100% - 2 * var(--universal-margin)); + margin: var(--universal-margin); + border: 0; + border-radius: calc(2 * var(--universal-border-radius)); + background: var(--progress-back-color); + color: var(--progress-fore-color); } + progress::-webkit-progress-value { + background: var(--progress-fore-color); + border-top-left-radius: calc(2 * var(--universal-border-radius)); + border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } + progress::-webkit-progress-bar { + background: var(--progress-back-color); } + progress::-moz-progress-bar { + background: var(--progress-fore-color); + border-top-left-radius: calc(2 * var(--universal-border-radius)); + border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } + progress[value="1000"]::-webkit-progress-value { + border-radius: calc(2 * var(--universal-border-radius)); } + progress[value="1000"]::-moz-progress-bar { + border-radius: calc(2 * var(--universal-border-radius)); } + progress.inline { + display: inline-block; + vertical-align: middle; + width: 60%; } + +:root { + --spinner-back-color: #ddd; + --spinner-fore-color: #555; } + +@keyframes spinner-donut-anim { + 0% { + transform: rotate(0deg); } + 100% { + transform: rotate(360deg); } } +.spinner { + display: inline-block; + margin: var(--universal-margin); + border: 0.25rem solid var(--spinner-back-color); + border-left: 0.25rem solid var(--spinner-fore-color); + border-radius: 50%; + width: 1.25rem; + height: 1.25rem; + animation: spinner-donut-anim 1.2s linear infinite; } + +/* + Custom elements for progress bars and spinners. +*/ +progress.primary { + --progress-fore-color: #1976d2; } + +progress.secondary { + --progress-fore-color: #d32f2f; } + +progress.tertiary { + --progress-fore-color: #308732; } + +.spinner.primary { + --spinner-fore-color: #1976d2; } + +.spinner.secondary { + --spinner-fore-color: #d32f2f; } + +.spinner.tertiary { + --spinner-fore-color: #308732; } + +/* + Definitions for icons - powered by Feather (https://feathericons.com/). +*/ +span[class^='icon-'] { + display: inline-block; + height: 1em; + width: 1em; + vertical-align: -0.125em; + background-size: contain; + margin: 0 calc(var(--universal-margin) / 4); } + span[class^='icon-'].secondary { + -webkit-filter: invert(25%); + filter: invert(25%); } + span[class^='icon-'].inverse { + -webkit-filter: invert(100%); + filter: invert(100%); } + +span.icon-alert { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12' y2='16'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-bookmark { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-calendar { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-credit { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1' y='4' width='22' height='16' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='1' y1='10' x2='23' y2='10'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-edit { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 14.66V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h5.34'%3E%3C/path%3E%3Cpolygon points='18 2 22 6 12 16 8 16 8 12 18 2'%3E%3C/polygon%3E%3C/svg%3E"); } +span.icon-link { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'%3E%3C/path%3E%3Cpolyline points='15 3 21 3 21 9'%3E%3C/polyline%3E%3Cline x1='10' y1='14' x2='21' y2='3'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-help { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3'%3E%3C/path%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='17' x2='12' y2='17'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-home { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'%3E%3C/path%3E%3Cpolyline points='9 22 9 12 15 12 15 22'%3E%3C/polyline%3E%3C/svg%3E"); } +span.icon-info { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='16' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='8' x2='12' y2='8'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-lock { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2' ry='2'%3E%3C/rect%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-mail { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z'%3E%3C/path%3E%3Cpolyline points='22,6 12,13 2,6'%3E%3C/polyline%3E%3C/svg%3E"); } +span.icon-location { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z'%3E%3C/path%3E%3Ccircle cx='12' cy='10' r='3'%3E%3C/circle%3E%3C/svg%3E"); } +span.icon-phone { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-rss { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9'%3E%3C/path%3E%3Cpath d='M4 4a16 16 0 0 1 16 16'%3E%3C/path%3E%3Ccircle cx='5' cy='19' r='1'%3E%3C/circle%3E%3C/svg%3E"); } +span.icon-search { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-settings { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'%3E%3C/circle%3E%3Cpath d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-share { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='18' cy='5' r='3'%3E%3C/circle%3E%3Ccircle cx='6' cy='12' r='3'%3E%3C/circle%3E%3Ccircle cx='18' cy='19' r='3'%3E%3C/circle%3E%3Cline x1='8.59' y1='13.51' x2='15.42' y2='17.49'%3E%3C/line%3E%3Cline x1='15.41' y1='6.51' x2='8.59' y2='10.49'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-cart { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='21' r='1'%3E%3C/circle%3E%3Ccircle cx='20' cy='21' r='1'%3E%3C/circle%3E%3Cpath d='M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-upload { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'%3E%3C/path%3E%3Cpolyline points='17 8 12 3 7 8'%3E%3C/polyline%3E%3Cline x1='12' y1='3' x2='12' y2='15'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-user { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'%3E%3C/path%3E%3Ccircle cx='12' cy='7' r='4'%3E%3C/circle%3E%3C/svg%3E"); } + +/* + Definitions for utilities and helper classes. +*/ +/* Utility module CSS variable definitions */ +:root { + --generic-border-color: rgba(0, 0, 0, 0.3); + --generic-box-shadow: 0 0.2857142857rem 0.2857142857rem 0 rgba(0, 0, 0, 0.125), 0 0.1428571429rem 0.1428571429rem -0.1428571429rem rgba(0, 0, 0, 0.125); } + +.hidden { + display: none !important; } + +.visually-hidden { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } + +.bordered { + border: 0.0714285714rem solid var(--generic-border-color) !important; } + +.rounded { + border-radius: var(--universal-border-radius) !important; } + +.circular { + border-radius: 50% !important; } + +.shadowed { + box-shadow: var(--generic-box-shadow) !important; } + +.responsive-margin { + margin: calc(var(--universal-margin) / 4) !important; } + @media screen and (min-width: 500px) { + .responsive-margin { + margin: calc(var(--universal-margin) / 2) !important; } } + @media screen and (min-width: 1280px) { + .responsive-margin { + margin: var(--universal-margin) !important; } } + +.responsive-padding { + padding: calc(var(--universal-padding) / 4) !important; } + @media screen and (min-width: 500px) { + .responsive-padding { + padding: calc(var(--universal-padding) / 2) !important; } } + @media screen and (min-width: 1280px) { + .responsive-padding { + padding: var(--universal-padding) !important; } } + +@media screen and (max-width: 499px) { + .hidden-sm { + display: none !important; } } +@media screen and (min-width: 500px) and (max-width: 1279px) { + .hidden-md { + display: none !important; } } +@media screen and (min-width: 1280px) { + .hidden-lg { + display: none !important; } } +@media screen and (max-width: 499px) { + .visually-hidden-sm { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } +@media screen and (min-width: 500px) and (max-width: 1279px) { + .visually-hidden-md { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } +@media screen and (min-width: 1280px) { + .visually-hidden-lg { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } + +/*# sourceMappingURL=mini-custom.css.map */ + +img[alt="ST logo"] { display: block; margin: auto; width: 75%; max-width: 250px; min-width: 71px; } +img[alt="Cube logo"] { float: right; width: 30%; max-width: 10rem; min-width: 8rem; padding-right: 1rem;} + +.figure { + display: block; + margin-left: auto; + margin-right: auto; + text-align: center; +} \ No newline at end of file diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/st_logo_2020.png b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/st_logo_2020.png new file mode 100644 index 0000000000000000000000000000000000000000..d6cebb5ac70e0594cbe37a6b60036a80ef3bed37 GIT binary patch literal 7520 zcmcI|WmKC@*KTl!K!Z~t6qn*&DDF_CK%q#B6QmH_DHL}I6b%;K-J$eBN|2xh0+bea zmtyV5bG|?CpZBcu=iF<}z4q*xz1LhL*PcBwx;m;Pgmi=e0DweYO-UaBz)*UWZ}4#+ zCC-V!SC16}H#HLv0Dy?%--0o{5_}H;Jf%=ql7H=+dziOk_)KzUSaiQ9L<^g!49k}} z?4y$V zrsn3Ul^TY`00G_J_8;F7Sr5c3Y)f-yOYl{fS0avfKJg7R%r!y-ohcBkr6XBZBkE)( z_t+tVV2}G1_CN!)yWes*wa-AGwk31N_T1`)4COlfz+o(9S90e?6jHV4)!>`j+oRqp z)gb?rtSdw<#&c?q!OKB+Ncn!kr5JR2EYan8HAPXBw*Oh-F(6GmaC!`$p7fl!_Cdu> z5@PUMR_K5&jgevDepWqepZVdMHR$q>ga=7k0ltW$HHVn>HRa!#(+BW_jN$5rx^MtR zzWT7tNWQeFzEp+86jOYI=I)*GZYEiXlf-Mw%tJ^ptL%2)%#PmUjxC4wx@%KxQ)8kO?|7E1 zd@5gd9_$*6nx?fj*iF_EJT*PYLFP}d8*Fw>cu3@&nm%V_C}V7HMmg|Nl#1J1^#)uz zZag|X>{6j-myvL}3(H8o3resNBq_jcuJuyT!QuXnNN&zG^tG? z>y*dy1#XfwyCE#UiLT(~LYAVwp)epErJLsHBA|l0xo)kxLAPob+7tFlr{7x8(#v|O zknK}QC6|~=cTJ0;x9MWMKua;LdTKIHX>35a@7{5y0MQ|zqsP64mM~`gJ&&R{pSUBA zf3Y>k>d|xdzBFztjtO~{y%@LUdwSgzEj=69hH3-NNWx7<|49%2%lvTEeE3_|$~iDd zlktnxf|NB>Bui)yY;%TXgWA;rhODxR!-4GzxKd473I)3;j zS4-Vun<^vqZ4)HbwVzq%5%)S!>Q(Y&PkF ze1ab_oy?_$PZT-mKJ3K^;6MrB*Wc$lkYJ_460AFYEq{AjlDxm;5GRwOsm>doJy3Z;a$FSu-q`X)Hw&o~?_`Dnpx4dOj6#)bGOdZbj4hD`l|&#v~K+WrGO zpLCVQg=*h=4H1sK)D*Pxtb#p`c+g-eK65k!CEZjLIrfm}5<4@KVqZ#8(S$vs{?Xv) zN(}CKeeLR%I)W!p(l-`utKmBbJk-On{)ciqUN5%?TS8uwKU(8}Mxhsb&qHL~DDcB@qi} z4z%efV#K69a#lShPt5}*7ME@^xunFR{k;|qp z`_Hgdj_Qle?%Ydlr3f^SdRkUncIj7qTiu85tA$v`#419Nlof8tjqUjO z!Rwyq$Krfh`(@MiE+)yie&jU^crprYV&?zN!2b33S2qtW+zB$nahDhVZiQ12bmcwYBcT8KS>v`jsuI@X zy^k^7>TM5Ndp@}pSl6vmkk*u`@C`z(gq||K2>y=Y#w1i`Nk2zAP7{_^ACq;bQmT<4 z;b~K3=?mhZX#~jQnZjdU={NFp^HRr~;^PXQ*UIHzkq}Xsn!56*ZCOOEt|^ zawUwGqs;zCEGKTz&(a(@h#0sCE+@`3Y<&}9!(;Pw&`C+d#D?`##&!@*ERaH0fksrh zfk2svh3!d~h{SC6BNKN2j6(lzC>S^_*eh{@gR zP$rV4$nqV1y|zYpd;nQr-`Vlp(5sQXx9AibC?xc7pUV)v2cWfHu3{KLbfP;;;`I&)mWqLcXt6s+5fps9R?K>hGR$5;=( zo#;zzQ5!w+(99p1_gh^?F#$tpMd+4%G|K`XG_#@A>30WD2L9!0a>wRASg`M?^z#)| zifb$d^KUD&3qLsr-@}r_7p${gdmRqhy819bj?yI-v({I?0o3_8d>CZmCzqH4{{QtD z|6dvgm<^~668G`6wLw4C4y-o9E9ZG3RiH^&;rrKSBT@bMR+!TlYo*9P;?Z>xORMV3ndQp9EyNn!!~j&x&$gDVke|t#!{QoegHm+sT7cSjwSu z)jZlx1pHrrx0&YCZWJ4xC&U%r_IwfJOxnYqYMcZn&_hgnKuls z>(Y$qjIhcweo^A_VVq_#UR&urF%UbI^><5L5zbV9owMQviM*_{@i|dke!!v8a_yG! zl%#ay{(6U_N3-)yeif3tx6>aQSf1r zO~OuNW<8a~bi6Xby0@tKw0@f1R!@+3S2nf#F&j~l0mrNCtjoZdPYob?g!Vx4F-uA2 z4uS>8eR?dA9i>C|cm-m5lO0m@$f(DB6Z<9Pe07xR`l4$ks3eZ@v5}1?^YNQy-tB(` zgUNZrGVf#b~`}jew;MQG1O~VDk_i*<)p9DfFfd;vLy4QZT zMYh|DxJg3-!{szUN*uo&`&DUkzq4qG2`Lj;Ar46DYUymcviS{Unhzmx z=LwZ-Lr{t1z?9Oip%!z{j+Z%_@u?C78I`V4fC`icG1c|2;`EoLK$ z)9|wrAV&V1Vgts~tQCw0X?X{74W"NJQ zW3BP!5c~4zzHJScwQK9L_%m%L`*q{1aW_3rObki~B~=Dwp`;@w`>xZ6;L_6oR^ecEcmup`yb}lgsmv zQByrxc)Qqm(Hwmq%fLjqcrJ5QR?z_*vb~Iy~RXUY8u-D8AqTzetwNNA8~N z$j&1>#IrkSslUqXW|l}q_TlTVKAjRI@~7(GLf4M>GM!3u_)y6ORe6BQUmrQ16%OdZKo(?AYXK$u@=)TPUi1EZaLBu zuEB(5GX2vcoHS%zMUW!DZ)&xRo@mhouk|hMgHIG>cO-Ah(0AMNlq@?cPpy==-!#qR zBov7l3G?P*KM(vU;Apo-(-Bw;sdQJkh~r)W$KRQKd!#(A8M34^MhD10Ra={AqSvjy z3>PkgA}f^@Rg1$dX=jaEB_V%_vn(W<111_s!g>CYrcwJTJ63Eeg6{_C`aMQIgKctR zHMjkr+y6gK!v6=6;CGl#?PqmiX`A@dmmvZ}-X$*q8}G(xq|voo`=$YZuQAa8f9ApK z1VQiEUQC=OO{|Nc8ZrXH208X|XCzIRO?+Nb55Jt@va9hqBpv)uY6ma-csvSlJoJOC zK;w~s?#r)K@gm*;((JsWHU-KvFTF)q>AzwPq)I+}OrSpxh!-CM1VEMfw1fpfVL7p{ z)I$rNp5kPYDsvXL>8nV{#0fa*lm`Z;0Z=c^1qveY2uk&7nhMRl`0EsvUuvwdF&o)PCVN3wmFBPegWzooF6y~b} zY>X2;LO~&rbvx59?(4^aR+s1C6hI4r&x9Q9jL9);KZEw_x%TWZXaMzK6|2XG9$IU% zkEq}t^YOaa4s`%7F31X-#SfMgNp+4R=g2G|O^W)6^2fEsmkTTaVhKCip+3qWuN8?y zaSD_k6%-@Ifhm`z02=ZWA-pi5`A=7ztHWpP2K5rCW{>!wIUOYrH``#bz>qVSH76=8 zyJ!sNBxt;dMTn}yzUTCq1!w;N7pzb?WJrQ50W+`meL{k8i0VhFsPUz(07k`l` zg1Ifl1fc-^p^MQCpK~Jk&L!*mWfNA!&MSu`sPmti>K-;I5Dk00nB3vOl4!JwjEx^X zWQsIp2Ea_>`9f@%zGl4i3FAO9=e$2^b_>_I*dqiLJ=@TejStM?^yX$9dW`#ha)PEF zPr0zUJX!j-juYK*olG_9axQniXhF|E}oSTG_S)FZ3sN4T@q zy{l;!{UGc};YVaT97tx3s7P$WsW2^*I+Hy;vqndG!9S?tZtDIRif1=bBsqtW-n7$O zWy}Z%jKSkgLX#1p>|#4l-!$c+kA`++Ixv(Rm`;Ilb3q3tD|QjaPQ8)BJ=8R*15?nL zJR{yuqOG&!JrSZ${#NY#b!k)yDajQ$A}fUQhe7ueN6h2Pj3wY5eo|7$PaJD zM69(ee1qlSyLn)Ln6)o53Lj)elqG}gb^c}qd(q&$8B5N%nSvEjUIoEXO^obv=A7QGZzNzjO*H=*b2!86Wnqdy~8ePkq@1D1)Q^O)JG;fUCV z`rgD}dJ{7BUyBbgoTL91w^q-CfBpDr?0R38`L%p9&Q#%r*@=9p-Ioqy+WscLq?jq5 zfyYNkxr7w)-(!c85mt!FjNJ4UE6P8p8sc#Kb4L1N3!yaCo9@t3n8s}K)1!w8x77xU zo-NY3SR*Pgt#~7F;y^J&Y%z^+C9wu;hN|TC7dqSHOB&kE)Q)6Ad(l&+tA@$@w0bhJ z6xc6EJ6nm{=|V7Vo&qcXc4i)D?X0Uk$p7~iI#ci?#fxvM z78`u%m5S@^_F;_foidufzP z&ueh-zU1yM&8~0lmOfkio-gBex`)?hCJcI8Jv*R0c|WUqSq z?RU?Rmm=3t_2C%%UW9c*D%T{T{EjryCKnsz9-*Bs0}M*xS&-odhCK5eS_Eqi&c6J4o|f&;uUT=p7Fedw#EUl4%Jv{w zq-cCF^otBvw~~$yj6O>>;VqU)3Ml&Atm$B(Ht8=+&x2VS5aWD&t*+04{@k^Gn~yHY zWYC%@ld;g_qz=k*;Iv&xs5M85cEZCU&n2Baf>R6*bN>V|!)eF&l#C93eAMLD=ZF7= zOISFfB5P;F!ngWD3jfMJE_53F&dFc{h2TwSbT*(h6!c}_5_UFeB_*DiyCrtQ7Byr@ z-aCWVt?J}YP7-lfelbrCgZ5mdv(^W&Yf^OvpI}#NbS1Lc`r4&t#3kM!utm&#a;?GR z-1FusfX7&?a9h`%8wf-ub7UXp44xm4w04)S$}}_hPqn-#IabO^bo6$K07>?%G5Xs( zA$*lz_K>lAJ_o<;fsP-*-%~O(716KRqVq+X@=5J~Z~bba(yWL`;EN`@Mr2it&Lkgb z&I|R5!`ZSk%)xFX*FYDaAh=5qWSY@rx1Du9J$$=lh#!~NcFJM&aOv)eqg_@`i^zJCR9a%_{k_i%msw5q z*3!~#Xx3r|VaAwiG}~9M#c`=$Uk6~xe)47ymW+;0DD_lV67L#ouJBa7mF{)X^?eIvPdOMu4ksr`jUP$~{x@?ev2 zdX#ite2RMim01PEg`;qfwg^;v8nx9F!CtNCvz)V{PVgCs*;_@_Rk*oLx@f7hJ7^^1 zu66b)mb!ZMXLZ%8dj-+JCMoWS-Wji-Q-~U7Pt~UiXMej8JcNjk<6?Wk9eLBIhu&Vo^0;AH> z;Q5^a!NZhP(vDfBv&?jdnQavv#8N0E{ZEgs>|1)qYo^t5 zIV$g~`C2%g$*(z4)8hJlK2mF-MJW#3%Cs6`uAvsgRtTo8n!Et)1pZx@_9I18 zw7ER9v~DyrC*R$do9aEw5r@B)YzHOLB^-c9Eu9D!sFmI8^VljVKE89{zY_8PTSF+J b^}%0^qYmp2WD(pA|JtZ4>nPPKybJpu3@X?! literal 0 HcmV?d00001 diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c new file mode 100644 index 000000000..abc86bd68 --- /dev/null +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c @@ -0,0 +1,888 @@ +/** + ****************************************************************************** + * @file tcpp0203.c + * @author MCD Application Team + * @brief This file provides the TCPP02/03 Type-C port protection driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "tcpp0203.h" + +#if defined(_TRACE) +#include "usbpd_core.h" +#include "usbpd_trace.h" +#include "string.h" +#include "stdio.h" +#endif /* _TRACE */ + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Components + * @{ + */ + +/** @addtogroup TCPP0203 + * @brief This file provides a set of functions needed to drive the + * TCPP02/03 Type-C port protection. + * @{ + */ + +/** @defgroup TCPP0203_Private_Constants Private Constants + * @{ + */ + +/* Compilation option in order to enable/disable a concistency check performed + after each I2C access into TCPP0203 registers : goal is to check that written value in Reg0 + is properly reflected into reg1 register content. + To enable register consistency check, please uncomment below definition. + To disable it, comment below line */ +/* #define TCPP0203_REGISTER_CONSISTENCY_CHECK */ + +/** @defgroup TCPP0203_Private_Types Private Types + * @{ + */ +/* TCPP02/03 Type-C port protection driver structure initialization */ +TCPP0203_Drv_t TCPP0203_Driver = +{ + TCPP0203_Init, + TCPP0203_DeInit, + TCPP0203_Reset, + TCPP0203_SetVConnSwitch, + TCPP0203_SetGateDriverProvider, + TCPP0203_SetGateDriverConsumer, + TCPP0203_SetPowerMode, + TCPP0203_SetVBusDischarge, + TCPP0203_SetVConnDischarge, + TCPP0203_GetVConnSwitchAck, + TCPP0203_GetGateDriverProviderAck, + TCPP0203_GetGateDriverConsumerAck, + TCPP0203_GetPowerModeAck, + TCPP0203_GetVBusDischargeAck, + TCPP0203_GetVConnDischargeAck, + TCPP0203_GetOCPVConnFlag, + TCPP0203_GetOCPVBusFlag, + TCPP0203_GetOVPVBusFlag, + TCPP0203_GetOVPCCFlag, + TCPP0203_GetOTPFlag, + TCPP0203_GetVBusOkFlag, + TCPP0203_ReadTCPPType, + TCPP0203_ReadVCONNPower, + TCPP0203_WriteCtrlRegister, + TCPP0203_ReadAckRegister, + TCPP0203_ReadFlagRegister, +}; + +/** + * @} + */ + +/** @defgroup TCPP0203_Private_Variables Private Variables + * @{ + */ +static uint8_t TCPP0203_DeviceType = TCPP0203_DEVICE_TYPE_03; + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) +static uint8_t Reg0_Expected_Value = 0x00; +static uint8_t Reg1_LastRead_Value = 0x00; +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/** @defgroup TCPP0203_Private_Function_Prototypes TCPP0203 Private Function Prototypes + * @{ + */ +static int32_t TCPP0203_ReadRegWrap(const void *handle, uint8_t Reg, uint8_t *Data, uint8_t Length); +static int32_t TCPP0203_WriteRegWrap(const void *handle, uint8_t Reg, uint8_t *Data, uint8_t Length); + +static int32_t TCPP0203_ModifyReg0(TCPP0203_Object_t *pObj, uint8_t Value, uint8_t Mask); + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) +static int32_t TCPP0203_CheckReg0Reg1(TCPP0203_Object_t *pObj, uint8_t Reg0ExpectedValue); +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + +/** + * @} + */ + +/** @defgroup TCPP0203_Exported_Functions TCPP0203 Exported Functions + * @{ + */ + +/** + * @brief Register Bus Io to component + * @param Component object pointer + * @retval Status of execution + */ +int32_t TCPP0203_RegisterBusIO(TCPP0203_Object_t *pObj, TCPP0203_IO_t *pIO) +{ + int32_t ret; + + if (pObj == NULL) + { + ret = TCPP0203_ERROR; + } + else + { + pObj->IO.Init = pIO->Init; + pObj->IO.DeInit = pIO->DeInit; + pObj->IO.Address = pIO->Address; + pObj->IO.WriteReg = pIO->WriteReg; + pObj->IO.ReadReg = pIO->ReadReg; + pObj->IO.GetTick = pIO->GetTick; + + pObj->Ctx.ReadReg = TCPP0203_ReadRegWrap; + pObj->Ctx.WriteReg = TCPP0203_WriteRegWrap; + pObj->Ctx.handle = pObj; + + if (pObj->IO.Init != NULL) + { + ret = pObj->IO.Init(); + } + else + { + ret = TCPP0203_ERROR; + } + } + + return ret; +} + +/** + * @brief Initializes the TCPP0203 interface + * @param pObj Pointer to component object + * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) + */ +int32_t TCPP0203_Init(TCPP0203_Object_t *pObj) +{ + int32_t ret = 0; + uint8_t tmp; + + if (pObj->IsInitialized == 0U) + { + /* Read TCPP Device type */ + ret += tcpp0203_read_reg(&pObj->Ctx, TCPP0203_READ_REG2, &tmp, 1); + + if (ret == TCPP0203_OK) + { + TCPP0203_DeviceType = (tmp & TCPP0203_DEVICE_TYPE_MSK); + } + else + { + TCPP0203_DeviceType = TCPP0203_DEVICE_TYPE_02; + } + pObj->IsInitialized = 1U; + } + + if (ret != TCPP0203_OK) + { + ret = TCPP0203_ERROR; + } + + return ret; +} + +/** + * @brief Deinitializes the TCPP0203 interface + * @param pObj Pointer to component object + * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) + */ +int32_t TCPP0203_DeInit(TCPP0203_Object_t *pObj) +{ + if (pObj->IsInitialized == 1U) + { + /* De-Initialize IO BUS layer */ + pObj->IO.DeInit(); + + pObj->IsInitialized = 0U; + } + + return TCPP0203_OK; +} + +/** + * @brief Resets TCPP0203 register (Reg0) + * @param pObj Pointer to component object + * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) + */ +int32_t TCPP0203_Reset(TCPP0203_Object_t *pObj) +{ + int32_t ret = TCPP0203_OK; + uint8_t tmp = TCPP0203_REG0_RST_VALUE; + + /* Write reset values in Reg0 register */ + if (tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, &tmp, 1) != TCPP0203_OK) + { + ret = TCPP0203_ERROR; + } + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) + Reg0_Expected_Value = TCPP0203_REG0_RST_VALUE; + Reg1_LastRead_Value = TCPP0203_REG0_RST_VALUE; +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + + return ret; +} + +/** + * @brief Configure TCPP0203 VConn Switch + * @param pObj Pointer to component object + * @param VConnSwitch VConn Switch requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_VCONN_SWITCH_OPEN VConn switch open + * @arg TCPP0203_VCONN_SWITCH_CC1 VConn closed on CC1 + * @arg TCPP0203_VCONN_SWITCH_CC2 VConn closed on CC2 + * @retval Component status + */ +int32_t TCPP0203_SetVConnSwitch(TCPP0203_Object_t *pObj, uint8_t VConnSwitch) +{ + int32_t ret = TCPP0203_OK; + + if ((VConnSwitch != TCPP0203_VCONN_SWITCH_OPEN) + && (VConnSwitch != TCPP0203_VCONN_SWITCH_CC1) + && (VConnSwitch != TCPP0203_VCONN_SWITCH_CC2)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update VConn switch setting in Writing register Reg0 */ + ret += TCPP0203_ModifyReg0(pObj, VConnSwitch, TCPP0203_VCONN_SWITCH_MSK); + } + + return ret; +} + +/** + * @brief Configure TCPP0203 Gate Driver for Provider path + * @param pObj Pointer to component object + * @param GateDriverProvider GDP switch load requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_GD_PROVIDER_SWITCH_OPEN GDP Switch Load Open + * @arg TCPP0203_GD_PROVIDER_SWITCH_CLOSED GDP Switch Load closed + * @retval Component status + */ +int32_t TCPP0203_SetGateDriverProvider(TCPP0203_Object_t *pObj, uint8_t GateDriverProvider) +{ + int32_t ret = TCPP0203_OK; + + if ((GateDriverProvider != TCPP0203_GD_PROVIDER_SWITCH_OPEN) + && (GateDriverProvider != TCPP0203_GD_PROVIDER_SWITCH_CLOSED)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update GDP Switch Load setting in Writing register Reg0 */ + if (GateDriverProvider == TCPP0203_GD_PROVIDER_SWITCH_CLOSED) + { + /* If Gate Driver Provider is to be closed, Gate Driver Consumer should be open */ + ret += TCPP0203_ModifyReg0(pObj, (GateDriverProvider | TCPP0203_GD_CONSUMER_SWITCH_OPEN), + (TCPP0203_GD_PROVIDER_SWITCH_MSK | TCPP0203_GD_CONSUMER_SWITCH_MSK)); + } + else + { + ret += TCPP0203_ModifyReg0(pObj, GateDriverProvider, TCPP0203_GD_PROVIDER_SWITCH_MSK); + } + } + + return ret; +} + +/** + * @brief Configure TCPP0203 Gate Driver for Consumer path + * @param pObj Pointer to component object + * @param GateDriverConsumer GDC switch load requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_GD_CONSUMER_SWITCH_OPEN GDC Switch Load Open + * @arg TCPP0203_GD_CONSUMER_SWITCH_CLOSED GDC Switch Load closed + * @retval Component status + */ +int32_t TCPP0203_SetGateDriverConsumer(TCPP0203_Object_t *pObj, uint8_t GateDriverConsumer) +{ + int32_t ret = TCPP0203_OK; + + /* Check if TCPP type is TCPP03. Otherwise, return error */ + if (TCPP0203_DeviceType != TCPP0203_DEVICE_TYPE_03) + { + return (TCPP0203_ERROR); + } + + if ((GateDriverConsumer != TCPP0203_GD_CONSUMER_SWITCH_OPEN) + && (GateDriverConsumer != TCPP0203_GD_CONSUMER_SWITCH_CLOSED)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update GDC Switch Load setting in Writing register Reg0 */ + if (GateDriverConsumer == TCPP0203_GD_CONSUMER_SWITCH_CLOSED) + { + /* If Gate Driver Consumer is to be closed, Gate Driver Provider should be open */ + ret += TCPP0203_ModifyReg0(pObj, (GateDriverConsumer | TCPP0203_GD_PROVIDER_SWITCH_OPEN), + (TCPP0203_GD_PROVIDER_SWITCH_MSK | TCPP0203_GD_CONSUMER_SWITCH_MSK)); + } + else + { + ret += TCPP0203_ModifyReg0(pObj, GateDriverConsumer, TCPP0203_GD_CONSUMER_SWITCH_MSK); + } + } + + return ret; +} + +/** + * @brief Configure TCPP0203 Power Mode + * @param pObj Pointer to component object + * @param PowerMode Power mode requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_POWER_MODE_HIBERNATE Hibernate + * @arg TCPP0203_POWER_MODE_LOWPOWER Low Power + * @arg TCPP0203_POWER_MODE_NORMAL Normal + * @retval Component status + */ +int32_t TCPP0203_SetPowerMode(TCPP0203_Object_t *pObj, uint8_t PowerMode) +{ + int32_t ret = TCPP0203_OK; + + if ((PowerMode != TCPP0203_POWER_MODE_HIBERNATE) + && (PowerMode != TCPP0203_POWER_MODE_LOWPOWER) + && (PowerMode != TCPP0203_POWER_MODE_NORMAL)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update Power Mode setting in Writing register Reg0 */ + ret += TCPP0203_ModifyReg0(pObj, PowerMode, TCPP0203_POWER_MODE_MSK); + } + + return ret; +} + +/** + * @brief Configure TCPP0203 Gate Driver for Provider path + * @param pObj Pointer to component object + * @param VBusDischarge VBUS Discharge requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_VBUS_DISCHARGE_OFF VBUS Discharge Off + * @arg TCPP0203_VBUS_DISCHARGE_ON VBUS Discharge On + * @retval Component status + */ +int32_t TCPP0203_SetVBusDischarge(TCPP0203_Object_t *pObj, uint8_t VBusDischarge) +{ + int32_t ret = TCPP0203_OK; + + if ((VBusDischarge != TCPP0203_VBUS_DISCHARGE_OFF) + && (VBusDischarge != TCPP0203_VBUS_DISCHARGE_ON)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update VBUS Discharge setting in Writing register Reg0 */ + ret += TCPP0203_ModifyReg0(pObj, VBusDischarge, TCPP0203_VBUS_DISCHARGE_MSK); + } + + return ret; +} + +/** + * @brief Configure TCPP0203 Gate Driver for Provider path + * @param pObj Pointer to component object + * @param VConnDischarge GDP switch load requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_VCONN_DISCHARGE_OFF VConn Discharge Off + * @arg TCPP0203_VCONN_DISCHARGE_ON VConn Discharge On + * @retval Component status + */ +int32_t TCPP0203_SetVConnDischarge(TCPP0203_Object_t *pObj, uint8_t VConnDischarge) +{ + int32_t ret = TCPP0203_OK; + + if ((VConnDischarge != TCPP0203_VCONN_DISCHARGE_OFF) + && (VConnDischarge != TCPP0203_VCONN_DISCHARGE_ON)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update VConn Discharge setting in Writing register Reg0 */ + ret += TCPP0203_ModifyReg0(pObj, VConnDischarge, TCPP0203_VCONN_DISCHARGE_MSK); + } + + return ret; +} + +/** + * @brief Get VConn switch Ack value + * @param pObj Pointer to component object + * @param pVConnSwitchAck Pointer on VConn switch Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_VCONN_SWITCH_OPEN VConn switch open Ack + * @arg TCPP0203_VCONN_SWITCH_CC1 VConn closed on CC1 Ack + * @arg TCPP0203_VCONN_SWITCH_CC2 VConn closed on CC2 Ack + * @retval Component status + */ +int32_t TCPP0203_GetVConnSwitchAck(TCPP0203_Object_t *pObj, uint8_t *pVConnSwitchAck) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pVConnSwitchAck = (tmp & TCPP0203_VCONN_SWITCH_ACK_MSK); + + return ret; +} + +/** + * @brief Get Gate Driver Provider Ack value + * @param pObj Pointer to component object + * @param pGateDriverProviderAck Pointer on Gate Driver Provider Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_GD_PROVIDER_SWITCH_ACK_OPEN Gate Driver Provider Open Ack + * @arg TCPP0203_GD_PROVIDER_SWITCH_ACK_CLOSED Gate Driver Provider Closed Ack + * @retval Component status + */ +int32_t TCPP0203_GetGateDriverProviderAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverProviderAck) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pGateDriverProviderAck = (tmp & TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK); + + return ret; +} + +/** + * @brief Get Gate Driver Consumer Ack value + * @param pObj Pointer to component object + * @param pGateDriverConsumerAck Pointer on Gate Driver Consumer Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_GD_CONSUMER_SWITCH_ACK_OPEN Gate Driver Consumer Open Ack + * @arg TCPP0203_GD_CONSUMER_SWITCH_ACK_CLOSED Gate Driver Consumer Closed Ack + * @retval Component status + */ +int32_t TCPP0203_GetGateDriverConsumerAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverConsumerAck) +{ + int32_t ret; + uint8_t tmp; + + /* Check if TCPP type is TCPP03. Otherwise, return error */ + if (TCPP0203_DeviceType != TCPP0203_DEVICE_TYPE_03) + { + return (TCPP0203_ERROR); + } + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pGateDriverConsumerAck = (tmp & TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK); + + return ret; +} + +/** + * @brief Get Power Mode Ack value + * @param pObj Pointer to component object + * @param pPowerModeAck Pointer on Power Mode Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_POWER_MODE_ACK_HIBERNATE Power Mode Hibernate Ack + * @arg TCPP0203_POWER_MODE_ACK_LOWPOWER Power Mode Low Power Ack + * @arg TCPP0203_POWER_MODE_ACK_NORMAL Power Mode Normal Ack + * @retval Component status + */ +int32_t TCPP0203_GetPowerModeAck(TCPP0203_Object_t *pObj, uint8_t *pPowerModeAck) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pPowerModeAck = (tmp & TCPP0203_POWER_MODE_ACK_MSK); + + return ret; +} + +/** + * @brief Get VBUS Discharge Ack value + * @param pObj Pointer to component object + * @param pVBusDischargeAck Pointer on VBUS Discharge Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_VBUS_DISCHARGE_ACK_OFF VBUS Discharge Off Ack + * @arg TCPP0203_VBUS_DISCHARGE_ACK_ON VBUS Discharge On Ack + * @retval Component status + */ +int32_t TCPP0203_GetVBusDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVBusDischargeAck) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pVBusDischargeAck = (tmp & TCPP0203_VBUS_DISCHARGE_ACK_MSK); + + return ret; +} + +/** + * @brief Get VConn Discharge Ack value + * @param pObj Pointer to component object + * @param pVConnDischargeAck Pointer on VConn Discharge Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_VCONN_DISCHARGE_ACK_OFF VConn Discharge Off Ack + * @arg TCPP0203_VCONN_DISCHARGE_ACK_ON VConn Discharge On Ack + * @retval Component status + */ +int32_t TCPP0203_GetVConnDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVConnDischargeAck) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pVConnDischargeAck = (tmp & TCPP0203_VCONN_DISCHARGE_ACK_MSK); + + return ret; +} + +/** + * @brief Get OCP VConn Flag value + * @param pObj Pointer to component object + * @param pOCPVConnFlag Pointer on OCP VConn Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_OCP_VCONN_RESET OCP VConn flag not set + * @arg TCPP0203_FLAG_OCP_VCONN_SET OCP VConn flag set + * @retval Component status + */ +int32_t TCPP0203_GetOCPVConnFlag(TCPP0203_Object_t *pObj, uint8_t *pOCPVConnFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pOCPVConnFlag = (tmp & TCPP0203_FLAG_OCP_VCONN_MSK); + + return ret; +} + +/** + * @brief Get OCP VBUS Flag value + * @param pObj Pointer to component object + * @param pGetOCPVBusFlag Pointer on OCP VBUS Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_OCP_VBUS_RESET OCP VBUS flag not set + * @arg TCPP0203_FLAG_OCP_VBUS_SET OCP VBUS flag set + * @retval Component status + */ +int32_t TCPP0203_GetOCPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pGetOCPVBusFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pGetOCPVBusFlag = (tmp & TCPP0203_FLAG_OCP_VBUS_MSK); + + return ret; +} + +/** + * @brief Get OVP VBUS Flag value + * @param pObj Pointer to component object + * @param pOVPVBusFlag Pointer on OVP VBUS Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_OVP_VBUS_RESET OVP VBUS flag not set + * @arg TCPP0203_FLAG_OVP_VBUS_SET OVP VBUS flag set + * @retval Component status + */ +int32_t TCPP0203_GetOVPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPVBusFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pOVPVBusFlag = (tmp & TCPP0203_FLAG_OVP_VBUS_MSK); + + return ret; +} + +/** + * @brief Get OVP CC Flag value + * @param pObj Pointer to component object + * @param pOVPCCFlag Pointer on OVP CC Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_OVP_CC_RESET OVP CC flag not set + * @arg TCPP0203_FLAG_OVP_CC_SET OVP CC flag set + * @retval Component status + */ +int32_t TCPP0203_GetOVPCCFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPCCFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pOVPCCFlag = (tmp & TCPP0203_FLAG_OVP_CC_MSK); + + return ret; +} + +/** + * @brief Get Over Temperature Flag value + * @param pObj Pointer to component object + * @param pOTPFlag Pointer on Over Temperature Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_OTP_RESET Over Temperature flag not set + * @arg TCPP0203_FLAG_OTP_SET Over Temperature flag set + * @retval Component status + */ +int32_t TCPP0203_GetOTPFlag(TCPP0203_Object_t *pObj, uint8_t *pOTPFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pOTPFlag = (tmp & TCPP0203_FLAG_OTP_MSK); + + return ret; +} + +/** + * @brief Get VBUS OK Flag value + * @param pObj Pointer to component object + * @param pVBusOkFlag Pointer on VBUS OK Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_VBUS_OK_RESET VBUS OK flag not set + * @arg TCPP0203_FLAG_VBUS_OK_SET VBUS OK flag set + * @retval Component status + */ +int32_t TCPP0203_GetVBusOkFlag(TCPP0203_Object_t *pObj, uint8_t *pVBusOkFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pVBusOkFlag = (tmp & TCPP0203_FLAG_VBUS_OK_MSK); + + return ret; +} + +/** + * @brief Get TCPP0203 Device Type value + * @param pObj Pointer to component object + * @param pTCPPType Pointer on TCPP0203 Device Type value + * This output parameter can be one of the following values: + * @arg TCPP0203_DEVICE_TYPE_02 TCPP02 Type + * @arg TCPP0203_DEVICE_TYPE_03 TCPP03 Type + * @retval Component status + */ +int32_t TCPP0203_ReadTCPPType(TCPP0203_Object_t *pObj, uint8_t *pTCPPType) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pTCPPType = (tmp & TCPP0203_DEVICE_TYPE_MSK); + + return ret; +} + +/** + * @brief Get VConn Power value + * @param pObj Pointer to component object + * @param pVCONNPower Pointer on VConn Power value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_VCONN_PWR_1W OCP VConn flag not set + * @arg TCPP0203_FLAG_VCONN_PWR_0_1W OCP VConn flag set + * @retval Component status + */ +int32_t TCPP0203_ReadVCONNPower(TCPP0203_Object_t *pObj, uint8_t *pVCONNPower) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pVCONNPower = (tmp & TCPP0203_FLAG_VCONN_PWR_MSK); + + return ret; +} + +/** + * @brief Set complete Ctrl register value (Reg 0) + * @param pObj Pointer to component object + * @param pCtrlRegister Pointer on Ctrl register value + * @retval Component status + */ +int32_t TCPP0203_WriteCtrlRegister(TCPP0203_Object_t *pObj, uint8_t *pCtrlRegister) +{ + int32_t ret; + + /* Update value in writing register (reg0) */ + ret = tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, pCtrlRegister, 1); + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) + Reg0_Expected_Value = *pCtrlRegister; +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + + return ret; +} + +/** + * @brief Get complete Ack register value + * @param pObj Pointer to component object + * @param pAckRegister Pointer on Ack register value + * @retval Component status + */ +int32_t TCPP0203_ReadAckRegister(TCPP0203_Object_t *pObj, uint8_t *pAckRegister) +{ + int32_t ret; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, pAckRegister, 1); + + return ret; +} + +/** + * @brief Get complete Flag register value + * @param pObj Pointer to component object + * @param pFlagRegister Pointer on Flag register value + * @retval Component status + */ +int32_t TCPP0203_ReadFlagRegister(TCPP0203_Object_t *pObj, uint8_t *pFlagRegister) +{ + int32_t ret; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, pFlagRegister, 1); + + return ret; +} + +/******************** Static functions ****************************************/ +/** + * @brief Wrap TCPP0203 read function to Bus IO function + * @param handle Component object handle + * @param Reg Target register address to read + * @param pData Buffer where Target register value should be stored + * @param Length buffer size to be read + * @retval error status + */ +static int32_t TCPP0203_ReadRegWrap(const void *handle, uint8_t Reg, uint8_t *pData, uint8_t Length) +{ + const TCPP0203_Object_t *pObj = (const TCPP0203_Object_t *)handle; + + return pObj->IO.ReadReg(pObj->IO.Address, Reg, pData, Length); +} + +/** + * @brief Wrap TCPP0203 write function to Bus IO function + * @param handle Component object handle + * @param Reg Target register address to write + * @param pData Target register value to be written + * @param Length Buffer size to be written + * @retval error status + */ +static int32_t TCPP0203_WriteRegWrap(const void *handle, uint8_t Reg, uint8_t *pData, uint8_t Length) +{ + const TCPP0203_Object_t *pObj = (const TCPP0203_Object_t *)handle; + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) + Reg0_Expected_Value = *pData; +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + + return pObj->IO.WriteReg(pObj->IO.Address, Reg, pData, Length); +} + +/** + * @brief TCPP0203 register update function to Bus IO function + * @param handle Component object handle + * @param Reg Target register address to write + * @param pData Target register value to be written + * @param Length Buffer size to be written + * @retval error status + */ +static int32_t TCPP0203_ModifyReg0(TCPP0203_Object_t *pObj, uint8_t Value, uint8_t Mask) +{ + int32_t ret; + uint8_t tmp; + + /* Read current content of ACK register (reflects content of bits set to 1 in Writing register Reg0) */ + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + + /* Update only the area dedicated to Mask */ + tmp &= ~(Mask); + tmp |= (Value & Mask); + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) + Reg0_Expected_Value = tmp; +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + + /* Update value in writing register (reg0) */ + ret += tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, &tmp, 1); + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) + ret += TCPP0203_CheckReg0Reg1(pObj, Reg0_Expected_Value); +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + + return ret; +} + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) +/** + * @brief TCPP0203 register control function between Reg0 and Reg1 value + * @param handle Component object handle + * @param Reg0ExpectedValue Value expected in Reg0 (built after all calls to write functions) + * @retval error status + */ +static int32_t TCPP0203_CheckReg0Reg1(TCPP0203_Object_t *pObj, uint8_t Reg0ExpectedValue) +{ + int32_t ret; + + /* Read current content of ACK register (expected to reflect content of bits set to 1 in Writing register Reg0) */ + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &Reg1_LastRead_Value, 1); + +#ifdef _TRACE + char str[12]; + sprintf(str, "Exp0_0x%02x", Reg0ExpectedValue); + USBPD_TRACE_Add(USBPD_TRACE_DEBUG, 0U, 0U, (uint8_t *)str, sizeof(str) - 1U); + sprintf(str, "Reg1_0x%02x", Reg1_LastRead_Value); + USBPD_TRACE_Add(USBPD_TRACE_DEBUG, 0U, 0U, (uint8_t *)str, sizeof(str) - 1U); +#endif /* _TRACE */ + + /* Control if Reg1 value is same as Reg0 expected one */ + if (Reg1_LastRead_Value != Reg0ExpectedValue) + { + while (1); + } + + return ret; +} +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + + diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h new file mode 100644 index 000000000..f2933f758 --- /dev/null +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h @@ -0,0 +1,355 @@ +/** + ****************************************************************************** + * @file tcpp0203.h + * @author MCD Application Team + * @brief This file contains all the functions prototypes for the + * tcpp0203.c driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef TCPP0203_H +#define TCPP0203_H + +/* Includes ------------------------------------------------------------------*/ +#include "tcpp0203_reg.h" +#include + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Component + * @{ + */ + +/** @addtogroup TCPP0203 + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup TCPP0203_Exported_Types TCPP0203 Exported Types + * @{ + */ +typedef int32_t (*TCPP0203_Init_Func)(void); +typedef int32_t (*TCPP0203_DeInit_Func)(void); +typedef int32_t (*TCPP0203_GetTick_Func)(void); +typedef int32_t (*TCPP0203_WriteReg_Func)(uint16_t, uint16_t, uint8_t *, uint16_t); +typedef int32_t (*TCPP0203_ReadReg_Func)(uint16_t, uint16_t, uint8_t *, uint16_t); + +typedef struct +{ + TCPP0203_Init_Func Init; + TCPP0203_DeInit_Func DeInit; + uint16_t Address; + TCPP0203_WriteReg_Func WriteReg; + TCPP0203_ReadReg_Func ReadReg; + TCPP0203_GetTick_Func GetTick; +} TCPP0203_IO_t; + + +typedef struct +{ + TCPP0203_IO_t IO; + TCPP0203_ctx_t Ctx; + uint8_t IsInitialized; +} TCPP0203_Object_t; + +typedef struct +{ + int32_t (*Init)(TCPP0203_Object_t *); + int32_t (*DeInit)(TCPP0203_Object_t *); + int32_t (*Reset)(TCPP0203_Object_t *); + int32_t (*SetVConnSwitch)(TCPP0203_Object_t *, uint8_t); + int32_t (*SetGateDriverProvider)(TCPP0203_Object_t *, uint8_t); + int32_t (*SetGateDriverConsumer)(TCPP0203_Object_t *, uint8_t); + int32_t (*SetPowerMode)(TCPP0203_Object_t *, uint8_t); + int32_t (*SetVBusDischarge)(TCPP0203_Object_t *, uint8_t); + int32_t (*SetVConnDischarge)(TCPP0203_Object_t *, uint8_t); + int32_t (*GetVConnSwitchAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetGateDriverProviderAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetGateDriverConsumerAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetPowerModeAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetVBusDischargeAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetVConnDischargeAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetOCPVConnFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetOCPVBusFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetOVPVBusFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetOVPCCFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetOTPFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetVBusOkFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*ReadTCPPType)(TCPP0203_Object_t *, uint8_t *); + int32_t (*ReadVCONNPower)(TCPP0203_Object_t *, uint8_t *); + int32_t (*WriteCtrlRegister)(TCPP0203_Object_t *, uint8_t *); + int32_t (*ReadAckRegister)(TCPP0203_Object_t *, uint8_t *); + int32_t (*ReadFlagRegister)(TCPP0203_Object_t *, uint8_t *); +} TCPP0203_Drv_t; + +/** + * @} + */ + +/** @defgroup TCPP0203_Exported_Constants TCPP0203 Exported Constants + * @{ + */ +/** + * @brief TCPP0203 Driver Response codes + */ +#define TCPP0203_OK (0) +#define TCPP0203_ERROR (-1) + +/** + * @brief TCPP0203 possible I2C Addresses + */ +#define TCPP0203_I2C_ADDRESS_X68 (0x68U) +#define TCPP0203_I2C_ADDRESS_X6A (0x6AU) + +/** + * @brief TCPP0203 Reg0 Reset Value + */ +#define TCPP0203_REG0_RST_VALUE TCPP0203_GD_CONSUMER_SWITCH_CLOSED + +/** + * @brief TCPP0203 VCONN Switch + */ +#define TCPP0203_VCONN_SWITCH_POS (0U) +#define TCPP0203_VCONN_SWITCH_MSK (0x03U << TCPP0203_VCONN_SWITCH_POS) +#define TCPP0203_VCONN_SWITCH_OPEN (0x00U) +#define TCPP0203_VCONN_SWITCH_CC1 (0x01U << TCPP0203_VCONN_SWITCH_POS) +#define TCPP0203_VCONN_SWITCH_CC2 (0x02U << TCPP0203_VCONN_SWITCH_POS) + +/** + * @brief TCPP0203 Gate Driver Provider values + */ +#define TCPP0203_GD_PROVIDER_SWITCH_POS (2U) +#define TCPP0203_GD_PROVIDER_SWITCH_MSK (0x01U << TCPP0203_GD_PROVIDER_SWITCH_POS) +#define TCPP0203_GD_PROVIDER_SWITCH_OPEN (0x00U) +#define TCPP0203_GD_PROVIDER_SWITCH_CLOSED (TCPP0203_GD_PROVIDER_SWITCH_MSK) + +/** + * @brief TCPP0203 Gate Driver Consumer values + */ +#define TCPP0203_GD_CONSUMER_SWITCH_POS (3U) +#define TCPP0203_GD_CONSUMER_SWITCH_MSK (0x01U << TCPP0203_GD_CONSUMER_SWITCH_POS) +#define TCPP0203_GD_CONSUMER_SWITCH_CLOSED (0x00U) +#define TCPP0203_GD_CONSUMER_SWITCH_OPEN (TCPP0203_GD_CONSUMER_SWITCH_MSK) + +/** + * @brief TCPP0203 Power Mode values + */ +#define TCPP0203_POWER_MODE_POS (4U) +#define TCPP0203_POWER_MODE_MSK (0x03U << TCPP0203_POWER_MODE_POS) +#define TCPP0203_POWER_MODE_HIBERNATE (0x00U) +#define TCPP0203_POWER_MODE_LOWPOWER (0x02U << TCPP0203_POWER_MODE_POS) +#define TCPP0203_POWER_MODE_NORMAL (0x01U << TCPP0203_POWER_MODE_POS) + +/** + * @brief TCPP0203 VBUS Discharge management + */ +#define TCPP0203_VBUS_DISCHARGE_POS (6U) +#define TCPP0203_VBUS_DISCHARGE_MSK (0x01U << TCPP0203_VBUS_DISCHARGE_POS) +#define TCPP0203_VBUS_DISCHARGE_OFF (0x00U) +#define TCPP0203_VBUS_DISCHARGE_ON (TCPP0203_VBUS_DISCHARGE_MSK) + +/** + * @brief TCPP0203 VConn Discharge management + */ +#define TCPP0203_VCONN_DISCHARGE_POS (7U) +#define TCPP0203_VCONN_DISCHARGE_MSK (0x01U << TCPP0203_VCONN_DISCHARGE_POS) +#define TCPP0203_VCONN_DISCHARGE_OFF (0x00U) +#define TCPP0203_VCONN_DISCHARGE_ON (TCPP0203_VCONN_DISCHARGE_MSK) + +/** + * @brief TCPP0203 VCONN Switch Acknowledge + */ +#define TCPP0203_VCONN_SWITCH_ACK_POS (0U) +#define TCPP0203_VCONN_SWITCH_ACK_MSK (0x03U << TCPP0203_VCONN_SWITCH_ACK_POS) +#define TCPP0203_VCONN_SWITCH_ACK_OPEN (0x00U) +#define TCPP0203_VCONN_SWITCH_ACK_CC1 (0x02U << TCPP0203_VCONN_SWITCH_ACK_POS) +#define TCPP0203_VCONN_SWITCH_ACK_CC2 (0x01U << TCPP0203_VCONN_SWITCH_ACK_POS) + +/** + * @brief TCPP0203 Gate Driver Provider Acknowledge + */ +#define TCPP0203_GD_PROVIDER_SWITCH_ACK_POS (2U) +#define TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK (0x01U << TCPP0203_GD_PROVIDER_SWITCH_ACK_POS) +#define TCPP0203_GD_PROVIDER_SWITCH_ACK_OPEN (0x00U) +#define TCPP0203_GD_PROVIDER_SWITCH_ACK_CLOSED (TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK) + +/** + * @brief TCPP0203 Gate Driver Consumer Acknowledge + */ +#define TCPP0203_GD_CONSUMER_SWITCH_ACK_POS (3U) +#define TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK (0x01U << TCPP0203_GD_CONSUMER_SWITCH_ACK_POS) +#define TCPP0203_GD_CONSUMER_SWITCH_ACK_CLOSED (0x00U) +#define TCPP0203_GD_CONSUMER_SWITCH_ACK_OPEN (TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK) + +/** + * @brief TCPP0203 Power Mode Acknowledge + */ +#define TCPP0203_POWER_MODE_ACK_POS (4U) +#define TCPP0203_POWER_MODE_ACK_MSK (0x03U << TCPP0203_POWER_MODE_ACK_POS) +#define TCPP0203_POWER_MODE_ACK_HIBERNATE (0x00U) +#define TCPP0203_POWER_MODE_ACK_LOWPOWER (0x01U << TCPP0203_POWER_MODE_ACK_POS) +#define TCPP0203_POWER_MODE_ACK_NORMAL (0x02U << TCPP0203_POWER_MODE_ACK_POS) + +/** + * @brief TCPP0203 VBUS Discharge Acknowledge + */ +#define TCPP0203_VBUS_DISCHARGE_ACK_POS (6U) +#define TCPP0203_VBUS_DISCHARGE_ACK_MSK (0x01U << TCPP0203_VBUS_DISCHARGE_ACK_POS) +#define TCPP0203_VBUS_DISCHARGE_ACK_OFF (0x00U) +#define TCPP0203_VBUS_DISCHARGE_ACK_ON (TCPP0203_VBUS_DISCHARGE_ACK_MSK) + +/** + * @brief TCPP0203 VConn Discharge Acknowledge + */ +#define TCPP0203_VCONN_DISCHARGE_ACK_POS (7U) +#define TCPP0203_VCONN_DISCHARGE_ACK_MSK (0x01U << TCPP0203_VCONN_DISCHARGE_ACK_POS) +#define TCPP0203_VCONN_DISCHARGE_ACK_OFF (0x00U) +#define TCPP0203_VCONN_DISCHARGE_ACK_ON (TCPP0203_VCONN_DISCHARGE_ACK_MSK) + +/** + * @brief TCPP0203 OCP Vconn Flag management + */ +#define TCPP0203_FLAG_OCP_VCONN_POS (0U) +#define TCPP0203_FLAG_OCP_VCONN_MSK (0x01U << TCPP0203_FLAG_OCP_VCONN_POS) +#define TCPP0203_FLAG_OCP_VCONN_SET (TCPP0203_FLAG_OCP_VCONN_MSK) +#define TCPP0203_FLAG_OCP_VCONN_RESET (0x00U) + +/** + * @brief TCPP0203 OCP VBUS Flag management + */ +#define TCPP0203_FLAG_OCP_VBUS_POS (1U) +#define TCPP0203_FLAG_OCP_VBUS_MSK (0x01U << TCPP0203_FLAG_OCP_VBUS_POS) +#define TCPP0203_FLAG_OCP_VBUS_SET (TCPP0203_FLAG_OCP_VBUS_MSK) +#define TCPP0203_FLAG_OCP_VBUS_RESET (0x00U) + +/** + * @brief TCPP0203 OVP VBUS Flag management + */ +#define TCPP0203_FLAG_OVP_VBUS_POS (2U) +#define TCPP0203_FLAG_OVP_VBUS_MSK (0x01U << TCPP0203_FLAG_OVP_VBUS_POS) +#define TCPP0203_FLAG_OVP_VBUS_SET (TCPP0203_FLAG_OVP_VBUS_MSK) +#define TCPP0203_FLAG_OVP_VBUS_RESET (0x00U) + +/** + * @brief TCPP0203 OVP CC Flag management + */ +#define TCPP0203_FLAG_OVP_CC_POS (3U) +#define TCPP0203_FLAG_OVP_CC_MSK (0x01U << TCPP0203_FLAG_OVP_CC_POS) +#define TCPP0203_FLAG_OVP_CC_SET (TCPP0203_FLAG_OVP_CC_MSK) +#define TCPP0203_FLAG_OVP_CC_RESET (0x00U) + +/** + * @brief TCPP0203 OTP Flag management + */ +#define TCPP0203_FLAG_OTP_POS (4U) +#define TCPP0203_FLAG_OTP_MSK (0x01U << TCPP0203_FLAG_OTP_POS) +#define TCPP0203_FLAG_OTP_SET (TCPP0203_FLAG_OTP_MSK) +#define TCPP0203_FLAG_OTP_RESET (0x00U) + +/** + * @brief TCPP0203 VBUS OK Flag management + */ +#define TCPP0203_FLAG_VBUS_OK_POS (5U) +#define TCPP0203_FLAG_VBUS_OK_MSK (0x01U << TCPP0203_FLAG_VBUS_OK_POS) +#define TCPP0203_FLAG_VBUS_OK_SET (TCPP0203_FLAG_VBUS_OK_MSK) +#define TCPP0203_FLAG_VBUS_OK_RESET (0x00U) + +/** + * @brief TCPP0203 VConn Power + */ +#define TCPP0203_FLAG_VCONN_PWR_POS (6U) +#define TCPP0203_FLAG_VCONN_PWR_MSK (0x01U << TCPP0203_FLAG_VCONN_PWR_POS) +#define TCPP0203_FLAG_VCONN_PWR_1W (TCPP0203_FLAG_VCONN_PWR_MSK) +#define TCPP0203_FLAG_VCONN_PWR_0_1W (0x00U) + +/** + * @brief TCPP0203 Device Type + */ +#define TCPP0203_DEVICE_TYPE_POS (7U) +#define TCPP0203_DEVICE_TYPE_MSK (0x01U << TCPP0203_DEVICE_TYPE_POS) +#define TCPP0203_DEVICE_TYPE_02 (TCPP0203_DEVICE_TYPE_MSK) +#define TCPP0203_DEVICE_TYPE_03 (0x00U) + +/** + * @} + */ + +/** @defgroup TCPP0203_Exported_Macros TCPP0203 Exported Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup TCPP0203_Exported_Functions TCPP0203 Exported Functions + * @{ + */ + +/*------------------------------------------------------------------------------ + TCPP02/03 Type-C port protection functions +------------------------------------------------------------------------------*/ +/* High Layer codec functions */ +int32_t TCPP0203_RegisterBusIO(TCPP0203_Object_t *pObj, TCPP0203_IO_t *pIO); +int32_t TCPP0203_Init(TCPP0203_Object_t *pObj); +int32_t TCPP0203_DeInit(TCPP0203_Object_t *pObj); +int32_t TCPP0203_Reset(TCPP0203_Object_t *pObj); +int32_t TCPP0203_SetVConnSwitch(TCPP0203_Object_t *pObj, uint8_t VConnSwitch); +int32_t TCPP0203_SetGateDriverProvider(TCPP0203_Object_t *pObj, uint8_t GateDriverProvider); +int32_t TCPP0203_SetGateDriverConsumer(TCPP0203_Object_t *pObj, uint8_t GateDriverConsumer); +int32_t TCPP0203_SetPowerMode(TCPP0203_Object_t *pObj, uint8_t PowerMode); +int32_t TCPP0203_SetVBusDischarge(TCPP0203_Object_t *pObj, uint8_t VBusDischarge); +int32_t TCPP0203_SetVConnDischarge(TCPP0203_Object_t *pObj, uint8_t VConnDischarge); +int32_t TCPP0203_GetVConnSwitchAck(TCPP0203_Object_t *pObj, uint8_t *pVConnSwitchAck); +int32_t TCPP0203_GetGateDriverProviderAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverProviderAck); +int32_t TCPP0203_GetGateDriverConsumerAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverConsumerAck); +int32_t TCPP0203_GetPowerModeAck(TCPP0203_Object_t *pObj, uint8_t *pPowerModeAck); +int32_t TCPP0203_GetVBusDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVBusDischargeAck); +int32_t TCPP0203_GetVConnDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVConnDischargeAck); +int32_t TCPP0203_GetOCPVConnFlag(TCPP0203_Object_t *pObj, uint8_t *pOCPVConnFlag); +int32_t TCPP0203_GetOCPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pGetOCPVBusFlag); +int32_t TCPP0203_GetOVPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPVBusFlag); +int32_t TCPP0203_GetOVPCCFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPCCFlag); +int32_t TCPP0203_GetOTPFlag(TCPP0203_Object_t *pObj, uint8_t *pOTPFlag); +int32_t TCPP0203_GetVBusOkFlag(TCPP0203_Object_t *pObj, uint8_t *pVBusOkFlag); +int32_t TCPP0203_ReadTCPPType(TCPP0203_Object_t *pObj, uint8_t *pTCPPType); +int32_t TCPP0203_ReadVCONNPower(TCPP0203_Object_t *pObj, uint8_t *pVCONNPower); +int32_t TCPP0203_WriteCtrlRegister(TCPP0203_Object_t *pObj, uint8_t *pCtrlRegister); +int32_t TCPP0203_ReadAckRegister(TCPP0203_Object_t *pObj, uint8_t *pAckRegister); +int32_t TCPP0203_ReadFlagRegister(TCPP0203_Object_t *pObj, uint8_t *pFlagRegister); + +/** + * @} + */ + +/* TCPP02/03 Type-C port protection driver structure */ +extern TCPP0203_Drv_t TCPP0203_Driver; + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* TCPP0203_H */ + + diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c new file mode 100644 index 000000000..5194172db --- /dev/null +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c @@ -0,0 +1,75 @@ +/** + ****************************************************************************** + * @file tcpp0203_reg.c + * @author MCD Application Team + * @brief This file provides unitary register function to control the TCPP02-03 + * Type-C port protection driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "tcpp0203_reg.h" + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Components + * @{ + */ + +/** @addtogroup TCPP0203 + * @brief This file provides a set of functions needed to drive the + * TCPP02/03 Type-C port protection codec. + * @{ + */ + +/************** Generic Function *******************/ +/******************************************************************************* + * Function Name : tcpp0203_read_reg + * Description : Generic Reading function. It must be fulfilled with either + * I2C or SPI reading functions + * Input : Register Address, length of buffer + * Output : data Read + *******************************************************************************/ +int32_t tcpp0203_read_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length) +{ + return ctx->ReadReg(ctx->handle, reg, data, length); +} + +/******************************************************************************* + * Function Name : tcpp0203_write_reg + * Description : Generic Writing function. It must be fulfilled with either + * I2C or SPI writing function + * Input : Register Address, data to be written, length of buffer + * Output : None + *******************************************************************************/ +int32_t tcpp0203_write_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length) +{ + return ctx->WriteReg(ctx->handle, reg, data, length); +} + +/******************************************************************************/ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + + diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h new file mode 100644 index 000000000..29edc62db --- /dev/null +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h @@ -0,0 +1,100 @@ +/** + ****************************************************************************** + * @file tcpp0203_reg.h + * @author MCD Application Team + * @brief Header of tcpp0203_reg.c + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef TCPP0203_REG_H +#define TCPP0203_REG_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Component + * @{ + */ + +/** @addtogroup TCPP0203 + * @{ + */ + + +/** @defgroup TCPP0203_Exported_Constants TCPP0203 Exported Constants + * @{ + */ +/******************************************************************************/ +/****************************** REGISTER MAPPING ******************************/ +/******************************************************************************/ +#define TCPP0203_WRITE_REG 0x00U +#define TCPP0203_PROG_CTRL TCPP0203_WRITE_REG +#define TCPP0203_READ_REG1 0x01U +#define TCPP0203_ACK_REG TCPP0203_READ_REG1 +#define TCPP0203_READ_REG2 0x02U +#define TCPP0203_FLAG_REG TCPP0203_READ_REG2 + +/** + * @} + */ + +/************** Generic Function *******************/ + +typedef int32_t (*TCPP0203_Write_Func)(const void *, uint8_t, uint8_t *, uint8_t); +typedef int32_t (*TCPP0203_Read_Func)(const void *, uint8_t, uint8_t *, uint8_t); + +typedef struct +{ + TCPP0203_Write_Func WriteReg; + TCPP0203_Read_Func ReadReg; + void *handle; +} TCPP0203_ctx_t; + +/******************************************************************************* + * Register : Generic - All + * Address : Generic - All + * Bit Group Name: None + * Permission : W + *******************************************************************************/ +int32_t tcpp0203_write_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length); +int32_t tcpp0203_read_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length); + +#ifdef __cplusplus +} +#endif + +#endif /* TCPP0203_REG_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + + diff --git a/hw/bsp/stm32h7rs/family.c b/hw/bsp/stm32h7rs/family.c new file mode 100644 index 000000000..1fbbd3cdb --- /dev/null +++ b/hw/bsp/stm32h7rs/family.c @@ -0,0 +1,313 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 + * William D. Jones (thor0505@comcast.net), + * Ha Thach (tinyusb.org) + * Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + manufacturer: STMicroelectronics +*/ + +#include "stm32h7rsxx_hal.h" +#include "bsp/board_api.h" + +TU_ATTR_UNUSED static void Error_Handler(void) { } + +typedef struct { + GPIO_TypeDef* port; + GPIO_InitTypeDef pin_init; + uint8_t active_state; +} board_pindef_t; + +#include "board.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + +#ifdef UART_DEV +UART_HandleTypeDef UartHandle = { + .Instance = UART_DEV, + .Init = { + .BaudRate = CFG_BOARD_UART_BAUDRATE, + .WordLength = UART_WORDLENGTH_8B, + .StopBits = UART_STOPBITS_1, + .Parity = UART_PARITY_NONE, + .HwFlowCtl = UART_HWCONTROL_NONE, + .Mode = UART_MODE_TX_RX, + .OverSampling = UART_OVERSAMPLING_16, + } +}; +#endif + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ + +// Despite being call USB2_OTG_FS on some MCUs +// OTG_FS is marked as RHPort0 by TinyUSB to be consistent across stm32 port +void OTG_FS_IRQHandler(void) { + tusb_int_handler(0, true); +} + +// Despite being call USB1_OTG_HS on some MCUs +// OTG_HS is marked as RHPort1 by TinyUSB to be consistent across stm32 port +void OTG_HS_IRQHandler(void) { + tusb_int_handler(1, true); +} + +#ifdef TRACE_ETM +void trace_etm_init(void) { + // H7 trace pin is PE2 to PE6 + GPIO_InitTypeDef gpio_init; + gpio_init.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6; + gpio_init.Mode = GPIO_MODE_AF_PP; + gpio_init.Pull = GPIO_PULLUP; + gpio_init.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + gpio_init.Alternate = GPIO_AF0_TRACE; + HAL_GPIO_Init(GPIOE, &gpio_init); + + // Enable trace clk, also in D1 and D3 domain + DBGMCU->CR |= DBGMCU_CR_DBG_TRACECKEN | DBGMCU_CR_DBG_CKD1EN | DBGMCU_CR_DBG_CKD3EN; +} +#else + #define trace_etm_init() +#endif + +void board_init(void) { + HAL_Init(); + + HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY); + // Implemented in board.h + SystemClock_Config(); + + // Enable All GPIOs clocks + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + __HAL_RCC_GPIOM_CLK_ENABLE(); + __HAL_RCC_GPION_CLK_ENABLE(); + __HAL_RCC_GPIOO_CLK_ENABLE(); + __HAL_RCC_GPIOP_CLK_ENABLE(); + + trace_etm_init(); + + for (uint8_t i = 0; i < TU_ARRAY_SIZE(board_pindef); i++) { + HAL_GPIO_Init(board_pindef[i].port, &board_pindef[i].pin_init); + } + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); + +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // Explicitly disable systick to prevent its ISR runs before scheduler start + SysTick->CTRL &= ~1U; + + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + #ifdef USB_OTG_FS_PERIPH_BASE + NVIC_SetPriority(OTG_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); + #endif + + NVIC_SetPriority(OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + + +#ifdef UART_DEV + UART_CLK_EN(); + HAL_UART_Init(&UartHandle); +#endif + + //------------- USB FS -------------// +#if (CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 0) || (CFG_TUH_ENABLED && BOARD_TUH_RHPORT == 0) + // OTG_FS is marked as RHPort0 by TinyUSB to be consistent across stm32 port + + HAL_PWREx_EnableUSBVoltageDetector(); + HAL_PWREx_EnableUSBReg(); + + __HAL_RCC_USB2_OTG_FS_CLK_ENABLE(); + + // PM14 VUSB, PM10 ID, PM11 DM, PM12 DP + // Configure DM DP Pins + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOM, &GPIO_InitStruct); + + // This for ID line debug + GPIO_InitStruct.Pin = GPIO_PIN_10; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOM, &GPIO_InitStruct); + +#if OTG_FS_VBUS_SENSE + // Configure VBUS Pin + GPIO_InitStruct.Pin = GPIO_PIN_14; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOM, &GPIO_InitStruct); + + // Enable VBUS sense (B device) via pin PM14 + USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBDEN; +#else + // Disable VBUS sense (B device) + USB_OTG_FS->GCCFG &= ~USB_OTG_GCCFG_VBDEN; + + // B-peripheral session valid override enable + USB_OTG_FS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; + USB_OTG_FS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; +#endif // vbus sense +#endif + + //------------- USB HS -------------// +#if (CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 1) || (CFG_TUH_ENABLED && BOARD_TUH_RHPORT == 1) + + // Enable USB HS & ULPI Clocks + __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + __HAL_RCC_USBPHYC_CLK_ENABLE(); + + // Enable USB power + HAL_PWREx_EnableUSBVoltageDetector(); + HAL_PWREx_EnableUSBHSregulator(); + +#if OTG_HS_VBUS_SENSE + // Configure VBUS Pin + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; + HAL_GPIO_Init(GPIOM, &GPIO_InitStruct); + + // Enable VBUS sense (B device) via pin PM9 + USB_OTG_HS->GCCFG |= USB_OTG_GCCFG_VBDEN; +#else + // Disable VBUS sense (B device) + USB_OTG_HS->GCCFG &= ~USB_OTG_GCCFG_VBDEN; + +#if CFG_TUD_ENABLED && BOARD_TUD_RHPORT == 1 + // B-peripheral session valid override enable + USB_OTG_HS->GCCFG |= USB_OTG_GCCFG_VBVALEXTOEN; + USB_OTG_HS->GCCFG |= USB_OTG_GCCFG_VBVALOVAL; +#else + USB_OTG_HS->GCCFG |= USB_OTG_GCCFG_PULLDOWNEN; +#endif + +#endif +#endif + + board_init2(); + +#if CFG_TUH_ENABLED + board_vbus_set(BOARD_TUH_RHPORT, 1); +#endif +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { +#ifdef PINID_LED + board_pindef_t* pindef = &board_pindef[PINID_LED]; + GPIO_PinState pin_state = state == pindef->active_state ? GPIO_PIN_SET : GPIO_PIN_RESET; + HAL_GPIO_WritePin(pindef->port, pindef->pin_init.Pin, pin_state); +#else + (void) state; +#endif +} + +uint32_t board_button_read(void) { +#ifdef PINID_BUTTON + board_pindef_t* pindef = &board_pindef[PINID_BUTTON]; + return pindef->active_state == HAL_GPIO_ReadPin(pindef->port, pindef->pin_init.Pin); +#else + return 0; +#endif +} + +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; + uint32_t* id32 = (uint32_t*) (uintptr_t) id; + uint8_t const len = 12; + + 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) { +#ifdef UART_DEV + HAL_UART_Transmit(&UartHandle, (uint8_t * )(uintptr_t) + buf, len, 0xffff); + return len; +#else + (void) buf; (void) len; + return -1; +#endif +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +void SysTick_Handler(void) { + HAL_IncTick(); + system_ticks++; +} + +uint32_t board_millis(void) { + return system_ticks; +} + +#endif + +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) { +} diff --git a/hw/bsp/stm32h7rs/family.cmake b/hw/bsp/stm32h7rs/family.cmake new file mode 100644 index 000000000..add0dc43d --- /dev/null +++ b/hw/bsp/stm32h7rs/family.cmake @@ -0,0 +1,150 @@ +include_guard() + +set(ST_FAMILY h7rs) +set(ST_PREFIX stm32${ST_FAMILY}xx) + +set(ST_HAL_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver) +set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis_device_${ST_FAMILY}) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_PROCESSOR cortex-m7 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS STM32H7 CACHE INTERNAL "") + +# ---------------------- +# Port & Speed Selection +# ---------------------- +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 1) +endif () +if (NOT DEFINED RHPORT_HOST) + set(RHPORT_HOST 1) +endif () + +if (NOT DEFINED RHPORT_SPEED) + set(RHPORT_SPEED OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED) +endif () +if (NOT DEFINED RHPORT_DEVICE_SPEED) + list(GET RHPORT_SPEED ${RHPORT_DEVICE} RHPORT_DEVICE_SPEED) +endif () +if (NOT DEFINED RHPORT_HOST_SPEED) + list(GET RHPORT_SPEED ${RHPORT_HOST} RHPORT_HOST_SPEED) +endif () + +cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif() + + # Startup & Linker script + set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) + + if(NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_flash.ld) + endif() + set(LD_FILE_Clang ${LD_FILE_GNU}) + if(NOT DEFINED LD_FILE_IAR) + set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) + endif() + + add_library(${BOARD_TARGET} STATIC + ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_dma.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_i2c.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMSIS_5}/CMSIS/Core/Include + ${ST_CMSIS}/Include + ${ST_HAL_DRIVER}/Inc + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + BOARD_TUD_RHPORT=${RHPORT_DEVICE} + BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} + BOARD_TUH_RHPORT=${RHPORT_HOST} + BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_STM32H7RS ${RTOS}) + target_sources(${TARGET}-tinyusb PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ) + target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) + + # Link dependencies + target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_stlink(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/stm32h7rs/family.mk b/hw/bsp/stm32h7rs/family.mk new file mode 100644 index 000000000..e2d6d40e4 --- /dev/null +++ b/hw/bsp/stm32h7rs/family.mk @@ -0,0 +1,92 @@ +ST_FAMILY = h7rs +ST_PREFIX = stm32${ST_FAMILY}xx +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/${ST_PREFIX}_hal_driver + +UF2_FAMILY_ID = 0x6db66083 + +include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= cortex-m7 + +# ---------------------- +# Port & Speed Selection +# ---------------------- +RHPORT_SPEED ?= OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED +RHPORT_DEVICE ?= 1 +RHPORT_HOST ?= 1 + +# Determine RHPORT_DEVICE_SPEED if not defined +ifndef RHPORT_DEVICE_SPEED +ifeq ($(RHPORT_DEVICE), 0) + RHPORT_DEVICE_SPEED = $(firstword $(RHPORT_SPEED)) +else + RHPORT_DEVICE_SPEED = $(lastword $(RHPORT_SPEED)) +endif +endif + +# Determine RHPORT_HOST_SPEED if not defined +ifndef RHPORT_HOST_SPEED +ifeq ($(RHPORT_HOST), 0) + RHPORT_HOST_SPEED = $(firstword $(RHPORT_SPEED)) +else + RHPORT_HOST_SPEED = $(lastword $(RHPORT_SPEED)) +endif +endif + +# -------------- +# Compiler Flags +# -------------- +CFLAGS += \ + -DCFG_TUSB_MCU=OPT_MCU_STM32H7RS \ + -DBOARD_TUD_RHPORT=${RHPORT_DEVICE} \ + -DBOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} \ + -DBOARD_TUH_RHPORT=${RHPORT_HOST} \ + -DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} \ + +# GCC Flags +CFLAGS_GCC += \ + -flto \ + +# suppress warning caused by vendor mcu driver +CFLAGS_GCC += \ + -Wno-error=cast-align \ + -Wno-error=unused-parameter \ + +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs + +# ----------------- +# Sources & Include +# ----------------- + +SRC_C += \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ + src/portable/synopsys/dwc2/hcd_dwc2.c \ + src/portable/synopsys/dwc2/dwc2_common.c \ + $(ST_CMSIS)/Source/Templates/system_${ST_PREFIX}.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_dma.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_i2c.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pwr.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pwr_ex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_uart_ex.c \ + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc + +# Startup +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_$(MCU_VARIANT).s +SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT).s + +# Linker +LD_FILE_GCC = $(ST_CMSIS)/Source/Templates/gcc/linker/$(MCU_VARIANT)_flash.ld +LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash.icf diff --git a/hw/bsp/stm32h7rs/stm32h7rsxx_hal_conf.h b/hw/bsp/stm32h7rs/stm32h7rsxx_hal_conf.h new file mode 100644 index 000000000..ea074f7d7 --- /dev/null +++ b/hw/bsp/stm32h7rs/stm32h7rsxx_hal_conf.h @@ -0,0 +1,501 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32h7rsxx_hal_conf.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32h7rsxx_hal_conf.h. + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32H7RSxx_HAL_CONF_H +#define STM32H7RSxx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_CEC_MODULE_ENABLED */ +/* #define HAL_CORDIC_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_DCMIPP_MODULE_ENABLED */ +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_DTS_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +/* #define HAL_FDCAN_MODULE_ENABLED */ +/* #define HAL_GFXMMU_MODULE_ENABLED */ +/* #define HAL_GFXTIM_MODULE_ENABLED */ +/* #define HAL_GPU2D_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +/* #define HAL_HCD_MODULE_ENABLED */ +#define HAL_I2C_MODULE_ENABLED +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_I3C_MODULE_ENABLED */ +/* #define HAL_ICACHE_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_JPEG_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_LTDC_MODULE_ENABLED */ +/* #define HAL_MCE_MODULE_ENABLED */ +/* #define HAL_MDF_MODULE_ENABLED */ +/* #define HAL_MMC_MODULE_ENABLED */ +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_PCD_MODULE_ENABLED */ +/* #define HAL_PKA_MODULE_ENABLED */ +/* #define HAL_PSSI_MODULE_ENABLED */ +/* #define HAL_RAMECC_MODULE_ENABLED */ +/* #define HAL_RCC_MODULE_ENABLED */ +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +/* #define HAL_SAI_MODULE_ENABLED */ +/* #define HAL_SD_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_SMBUS_MODULE_ENABLED */ +/* #define HAL_SPDIFRX_MODULE_ENABLED */ +/* #define HAL_SPI_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_TIM_MODULE_ENABLED */ +#define HAL_UART_MODULE_ENABLED +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +#define HAL_XSPI_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) +#define HSE_VALUE 24000000UL /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT 100UL /*!< Time out for HSE start up (in ms) */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) +#define HSI_VALUE 64000000UL /*!< Value of the Internal oscillator in Hz */ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low-power oscillator (CSI) default value. + * This value is the default CSI range value after Reset. + */ +#if !defined (CSI_VALUE) +#define CSI_VALUE 4000000UL /*!< Value of the Internal oscillator in Hz */ +#endif /* CSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI48) value for USB OTG FS and RNG. + * This internal oscillator is mainly dedicated to provide a high precision clock to + * the USB peripheral by means of a special Clock Recovery System (CRS) circuitry. + * When the CRS is not used, the HSI48 RC oscillator runs on it default frequency + * which is subject to manufacturing process variations. + */ + #if !defined (HSI48_VALUE) + #define HSI48_VALUE 48000000UL /*!< Value of the Internal High Speed oscillator for USB OTG FS/RNG in Hz. + The real value my vary depending on manufacturing process variations. */ + #endif /* HSI48_VALUE */ + +/** +* @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) +#define LSI_VALUE 32000UL /*!< LSI Typical Value in Hz. + Value of the Internal Low Speed oscillator in Hz. + The real value may vary depending on the variations + in voltage and temperature.*/ +#endif /* LSI_VALUE */ + +/** +* @brief External Low Speed oscillator (LSE) value. +*/ +#if !defined (LSE_VALUE) +#define LSE_VALUE 32768UL /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT 5000UL /*!< Time out for LSE start up (in ms) */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for digital audio interfaces: SPI/I2S, SAI and ADF + * This value is used by the RCC HAL module to provide the digital audio interfaces + * frequency. This clock source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) +#define EXTERNAL_CLOCK_VALUE 48000UL /*!< Value of the external clock source in Hz */ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300UL /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY (15UL)/*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U + +/* ########################## Assert Selection ############################## */ +/** +* @brief Uncomment the line below to expanse the "assert_param" macro in the +* HAL drivers code +*/ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Register callback feature configuration ############### */ +/** +* @brief Set below the peripheral configuration to "1U" to add the support +* of HAL callback registration/unregistration feature for the HAL +* driver(s). This allows user application to provide specific callback +* functions thanks to HAL_PPP_RegisterCallback() rather than overwriting +* the default weak callback functions (see each stm32h7rsxx_hal_ppp.h file +* for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef +* for each PPP peripheral). +*/ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U +#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U +#define USE_HAL_DCMIPP_REGISTER_CALLBACKS 0U +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U +#define USE_HAL_GFXMMU_REGISTER_CALLBACKS 0U +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U +#define USE_HAL_JPEG_REGISTER_CALLBACKS 0U +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U +#define USE_HAL_MDF_REGISTER_CALLBACKS 0U +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U +#define USE_HAL_PKA_REGISTER_CALLBACKS 0U +#define USE_HAL_PSSI_REGISTER_CALLBACKS 0U +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U +#define USE_HAL_SD_REGISTER_CALLBACKS 0U +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U +#define USE_HAL_UART_REGISTER_CALLBACKS 0U +#define USE_HAL_USART_REGISTER_CALLBACKS 0U +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U +#define USE_HAL_XSPI_REGISTER_CALLBACKS 0U + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 1U + +/* ################## CRYP peripheral configuration ########################## */ + +#define USE_HAL_CRYP_SUSPEND_RESUME 0U + +/* ################## HASH peripheral configuration ########################## */ + +#define USE_HAL_HASH_SUSPEND_RESUME 0U + +/* ################## SDMMC peripheral configuration ######################### */ + +#define USE_SD_TRANSCEIVER 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32h7rsxx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32h7rsxx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32h7rsxx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32h7rsxx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32h7rsxx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32h7rsxx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_CORDIC_MODULE_ENABLED + #include "stm32h7rsxx_hal_cordic.h" +#endif /* HAL_CORDIC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32h7rsxx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32h7rsxx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DCMIPP_MODULE_ENABLED + #include "stm32h7rsxx_hal_dcmipp.h" +#endif /* HAL_DCMIPP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32h7rsxx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DTS_MODULE_ENABLED + #include "stm32h7rsxx_hal_dts.h" +#endif /* HAL_DTS_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32h7rsxx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32h7rsxx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_FDCAN_MODULE_ENABLED + #include "stm32h7rsxx_hal_fdcan.h" +#endif /* HAL_FDCAN_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32h7rsxx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_GFXMMU_MODULE_ENABLED + #include "stm32h7rsxx_hal_gfxmmu.h" +#endif /* HAL_GFXMMU_MODULE_ENABLED */ + +#ifdef HAL_GFXTIM_MODULE_ENABLED + #include "stm32h7rsxx_hal_gfxtim.h" +#endif /* HAL_GFXTIM_MODULE_ENABLED */ + +#ifdef HAL_GPU2D_MODULE_ENABLED + #include "stm32h7rsxx_hal_gpu2d.h" +#endif /* HAL_GPU2D_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32h7rsxx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32h7rsxx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32h7rsxx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32h7rsxx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_I3C_MODULE_ENABLED + #include "stm32h7rsxx_hal_i3c.h" +#endif /* HAL_I3C_MODULE_ENABLED */ + +#ifdef HAL_ICACHE_MODULE_ENABLED + #include "stm32h7rsxx_hal_icache.h" +#endif /* HAL_ICACHE_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32h7rsxx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32h7rsxx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_JPEG_MODULE_ENABLED + #include "stm32h7rsxx_hal_jpeg.h" +#endif /* HAL_JPEG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32h7rsxx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32h7rsxx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_MCE_MODULE_ENABLED + #include "stm32h7rsxx_hal_mce.h" +#endif /* HAL_MCE_MODULE_ENABLED */ + +#ifdef HAL_MDF_MODULE_ENABLED + #include "stm32h7rsxx_hal_mdf.h" +#endif /* HAL_MDF_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32h7rsxx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32h7rsxx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32h7rsxx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32h7rsxx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_PKA_MODULE_ENABLED + #include "stm32h7rsxx_hal_pka.h" +#endif /* HAL_PKA_MODULE_ENABLED */ + +#ifdef HAL_PSSI_MODULE_ENABLED + #include "stm32h7rsxx_hal_pssi.h" +#endif /* HAL_PSSI_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32h7rsxx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RAMECC_MODULE_ENABLED + #include "stm32h7rsxx_hal_ramecc.h" +#endif /* HAL_RAMECC_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32h7rsxx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32h7rsxx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32h7rsxx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32h7rsxx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32h7rsxx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32h7rsxx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32h7rsxx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32h7rsxx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32h7rsxx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32h7rsxx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32h7rsxx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32h7rsxx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32h7rsxx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32h7rsxx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_XSPI_MODULE_ENABLED + #include "stm32h7rsxx_hal_xspi.h" +#endif /* HAL_XSPI_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t *file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H7RSxx_HAL_CONF_H */ + diff --git a/src/portable/synopsys/dwc2/dwc2_info.md b/src/portable/synopsys/dwc2/dwc2_info.md index dec021f59..76bd251c7 100644 --- a/src/portable/synopsys/dwc2/dwc2_info.md +++ b/src/portable/synopsys/dwc2/dwc2_info.md @@ -1,58 +1,58 @@ -| | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5 HS | XMC4500 | GD32VF103 | -|:---------------------------|:----------------|:-------------|:--------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:-------------|:-------------|:------------| -| GUID | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00AEC000 | 0x00001000 | -| GSNPSID | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54292A | 0x00000000 | -| - specs version | 2.80a | 3.30a | 4.00a | 4.00a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 2.92a | 0.00W | -| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | -| GHWCFG2 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228F5930 | 0x00000000 | -| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | HNP SRP | HNP SRP | -| - arch | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | Slave only | -| - single_point | hub | hub | n/a | hub | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | n/a | hub | -| - hs_phy_type | UTMI+ | n/a | n/a | UTMI+/ULPI | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | n/a | n/a | -| - fs_phy_type | Dedicated | Dedicated | Dedicated | Shared ULPI | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | Dedicated | n/a | -| - num_dev_ep | 7 | 6 | 6 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | -| - num_host_ch | 7 | 13 | 7 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 13 | 0 | -| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - mul_proc_intrpt | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - nptx_q_depth | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - ptx_q_depth | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | -| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| GHWCFG3 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | -| - xfer_size_width | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | -| - packet_size_width | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | -| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - i2c_enable | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | -| - vendor_ctrl_itf | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | -| - optional_feature_removed | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - synch_reset | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - otg_adp_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - battery_charger_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | -| - dfifo_depth | 4080 | 498 | 200 | 896 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 634 | 0 | -| GHWCFG4 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | -| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - partial_powerdown | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - enhanced_lpm_support | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - phy_data_width | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8/16 bit | 8 bit | -| - ctrl_ep_num | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - iddg_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - vbus_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - a_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - b_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - session_end_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - num_dev_in_eps | 7 | 6 | 4 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | -| - dma_desc_enable | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | -| - dma_desc_dynamic | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | +| | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5 HS | ST H7S3 HS | XMC4500 | GD32VF103 | +|:---------------------------|:----------------|:-------------|:--------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:-------------|:-------------|:-------------|:------------| +| GUID | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00005000 | 0x00AEC000 | 0x00001000 | +| GSNPSID | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54411A | 0x4F54292A | 0x00000000 | +| - specs version | 2.80a | 3.30a | 4.00a | 4.00a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 4.11a | 2.92a | 0.00W | +| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | +| GHWCFG2 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228FE052 | 0x228F5930 | 0x00000000 | +| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | noHNP noSRP | HNP SRP | HNP SRP | +| - arch | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | DMA internal | Slave only | +| - single_point | hub | hub | n/a | hub | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | hub | n/a | hub | +| - hs_phy_type | UTMI+ | n/a | n/a | UTMI+/ULPI | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | UTMI+ | n/a | n/a | +| - fs_phy_type | Dedicated | Dedicated | Dedicated | Shared ULPI | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | n/a | Dedicated | n/a | +| - num_dev_ep | 7 | 6 | 6 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 8 | 6 | 0 | +| - num_host_ch | 7 | 13 | 7 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 15 | 13 | 0 | +| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - mul_proc_intrpt | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | +| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - nptx_q_depth | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - ptx_q_depth | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | +| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| GHWCFG3 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | +| - xfer_size_width | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | +| - packet_size_width | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | +| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - i2c_enable | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | +| - vendor_ctrl_itf | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | +| - optional_feature_removed | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - synch_reset | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - otg_adp_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | +| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - battery_charger_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | +| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | +| - dfifo_depth | 4080 | 498 | 200 | 896 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 952 | 634 | 0 | +| GHWCFG4 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | +| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - partial_powerdown | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +| - enhanced_lpm_support | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +| - phy_data_width | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | +| - ctrl_ep_num | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - iddg_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - vbus_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - a_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - b_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - session_end_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - num_dev_in_eps | 7 | 6 | 4 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 8 | 6 | 0 | +| - dma_desc_enable | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | +| - dma_desc_dynamic | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py index 25edcf22d..6ab4e0641 100755 --- a/src/portable/synopsys/dwc2/dwc2_info.py +++ b/src/portable/synopsys/dwc2/dwc2_info.py @@ -22,6 +22,7 @@ dwc2_reg_value = { 'ST H743/H750': [0x2300, 0x4F54330A, 0, 0x229FE190, 0x03B8D2E8, 0xE3F00030], 'ST L476 FS': [0x2000, 0x4F54310A, 0, 0x229ED520, 0x0200D1E8, 0x17F08030], 'ST U5A5 HS': [0x5000, 0x4F54411A, 0, 0x228FE052, 0x03B882E8, 0xE2103E30], + 'ST H7S3 HS': [0x5000, 0x4F54411A, 0, 0x228FE052, 0x03B882E8, 0xE2103E30], 'XMC4500': [0xAEC000, 0x4F54292A, 0, 0x228F5930, 0x027A01E5, 0xDBF08030], 'GD32VF103': [0x1000, 0, 0, 0, 0, 0], } From 979d79095953ee0cad25438aa560dbb032af2bd0 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 24 Jan 2025 17:13:38 +0100 Subject: [PATCH 045/382] Fix CI. Signed-off-by: HiFiPhile --- hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt | 2 +- .../boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css | 4 ++-- hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c | 2 -- hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h | 2 -- .../stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c | 2 -- .../stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h | 2 -- hw/bsp/stm32h7rs/stm32h7rsxx_hal_conf.h | 1 - 7 files changed, 3 insertions(+), 12 deletions(-) diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt index 3edc4d146..1cbbc544a 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt @@ -1,6 +1,6 @@ This software component is provided to you as part of a software package and applicable license terms are in the Package_license file. If you received this software component outside of a package or without applicable license terms, -the terms of the BSD-3-Clause license shall apply. +the terms of the BSD-3-Clause license shall apply. You may obtain a copy of the BSD-3-Clause at: https://opensource.org/licenses/BSD-3-Clause diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css index 3d9e81ad3..dd19969d1 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css @@ -78,7 +78,7 @@ h1 { h2 { font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) ); - border-style: none none solid none ; + border-style: none none solid none ; border-width: thin; border-color: var(--border-color); } h3 { @@ -1700,4 +1700,4 @@ img[alt="Cube logo"] { float: right; width: 30%; max-width: 10rem; min-width: 8r margin-left: auto; margin-right: auto; text-align: center; -} \ No newline at end of file +} diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c index abc86bd68..952ff16c9 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c @@ -884,5 +884,3 @@ static int32_t TCPP0203_CheckReg0Reg1(TCPP0203_Object_t *pObj, uint8_t Reg0Expec /** * @} */ - - diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h index f2933f758..271b534fc 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h @@ -351,5 +351,3 @@ extern TCPP0203_Drv_t TCPP0203_Driver; */ #endif /* TCPP0203_H */ - - diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c index 5194172db..8025fa85e 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c @@ -71,5 +71,3 @@ int32_t tcpp0203_write_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data /** * @} */ - - diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h index 29edc62db..92420e1fe 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h @@ -96,5 +96,3 @@ int32_t tcpp0203_read_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, /** * @} */ - - diff --git a/hw/bsp/stm32h7rs/stm32h7rsxx_hal_conf.h b/hw/bsp/stm32h7rs/stm32h7rsxx_hal_conf.h index ea074f7d7..6fd90abde 100644 --- a/hw/bsp/stm32h7rs/stm32h7rsxx_hal_conf.h +++ b/hw/bsp/stm32h7rs/stm32h7rsxx_hal_conf.h @@ -498,4 +498,3 @@ #endif #endif /* STM32H7RSxx_HAL_CONF_H */ - From d1ee2bf18fced22364537949c4a18e1c15c99b6d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 29 Jan 2025 15:14:25 +0100 Subject: [PATCH 046/382] Fix Auto speed display. Signed-off-by: HiFiPhile --- src/device/usbd.c | 23 ++++++++++++++++++++--- src/host/usbh.c | 23 ++++++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 2a6081673..8435b5c02 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -464,13 +464,30 @@ bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; // skip if already initialized } TU_ASSERT(rh_init); - - TU_LOG_USBD("USBD init on controller %u, speed = %s\r\n", rhport, - rh_init->speed == TUSB_SPEED_HIGH ? "High" : "Full"); +#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL + char const* speed_str = 0; + switch (rh_init->speed) { + case TUSB_SPEED_HIGH: + speed_str = "High"; + break; + case TUSB_SPEED_FULL: + speed_str = "Full"; + break; + case TUSB_SPEED_LOW: + speed_str = "Low"; + break; + case TUSB_SPEED_AUTO: + speed_str = "Auto"; + break; + default: + break; + } + TU_LOG_USBD("USBD init on controller %u, speed = %s\r\n", rhport, speed_str); TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(usbd_device_t)); TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(dcd_event_t)); TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_fifo_t)); TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_edpt_stream_t)); +#endif tu_varclr(&_usbd_dev); _usbd_queued_setup = 0; diff --git a/src/host/usbh.c b/src/host/usbh.c index a2994cde7..f022d93f1 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -365,9 +365,26 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { if (tuh_rhport_is_active(rhport)) { return true; // skip if already initialized } - - TU_LOG_USBH("USBH init on controller %u, speed = %s\r\n", rhport, - rh_init->speed == TUSB_SPEED_HIGH ? "High" : "Full"); +#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL + char const* speed_str = 0; + switch (rh_init->speed) { + case TUSB_SPEED_HIGH: + speed_str = "High"; + break; + case TUSB_SPEED_FULL: + speed_str = "Full"; + break; + case TUSB_SPEED_LOW: + speed_str = "Low"; + break; + case TUSB_SPEED_AUTO: + speed_str = "Auto"; + break; + default: + break; + } + TU_LOG_USBH("USBH init on controller %u, speed = %s\r\n", rhport, speed_str); +#endif // Init host stack if not already if (!tuh_inited()) { From cc626f35d212aef86b0aa7275eea016ae69b5de4 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 29 Jan 2025 15:16:02 +0100 Subject: [PATCH 047/382] msc_device: add async IO support. Signed-off-by: HiFiPhile --- src/class/msc/msc_device.c | 182 ++++++++++++++++++++++++++----------- src/class/msc/msc_device.h | 16 ++++ 2 files changed, 146 insertions(+), 52 deletions(-) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index dd66bfb6f..c7c926f4e 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -52,10 +52,18 @@ enum { MSC_STAGE_NEED_RESET, }; +enum { + MSC_NEXT_OP_NONE = 0, + MSC_NEXT_OP_READ10, + MSC_NEXT_OP_WRITE10, + MSC_NEXT_OP_STATUS +}; + typedef struct { TU_ATTR_ALIGNED(4) msc_cbw_t cbw; TU_ATTR_ALIGNED(4) msc_csw_t csw; + uint8_t rhport; uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; @@ -70,6 +78,10 @@ typedef struct { uint8_t sense_key; uint8_t add_sense_code; uint8_t add_sense_qualifier; +#if CFG_TUD_MSC_ASYNC_IO + uint8_t next_op; + uint32_t xferred_bytes; +#endif }mscd_interface_t; static mscd_interface_t _mscd_itf; @@ -82,31 +94,39 @@ CFG_TUD_MEM_SECTION static struct { // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize); -static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc); - -static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc); -static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes); +static void proc_read10_cmd(mscd_interface_t* p_msc); +static void proc_read10_next(mscd_interface_t* p_msc, int32_t nbytes); +static void proc_write10_cmd(mscd_interface_t* p_msc); +static void proc_write10_new_data(mscd_interface_t* p_msc, uint32_t xferred_bytes); +static void proc_write10_next(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes); +static bool proc_stage_status(mscd_interface_t* p_msc); +#if CFG_TUD_MSC_ASYNC_IO +static void tud_msc_async_io_done_cb(void* bytes_processed); +#endif TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) { return tu_bit_test(dir, 7); } -static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc) { +static inline bool send_csw(mscd_interface_t* p_msc) { // Data residue is always = host expect - actual transferred + uint8_t rhport = p_msc->rhport; p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; p_msc->stage = MSC_STAGE_STATUS_SENT; memcpy(_mscd_epbuf.buf, &p_msc->csw, sizeof(msc_csw_t)); return usbd_edpt_xfer(rhport, p_msc->ep_in , _mscd_epbuf.buf, sizeof(msc_csw_t)); } -static inline bool prepare_cbw(uint8_t rhport, mscd_interface_t* p_msc) { +static inline bool prepare_cbw(mscd_interface_t* p_msc) { + uint8_t rhport = p_msc->rhport; p_msc->stage = MSC_STAGE_CMD; return usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, sizeof(msc_cbw_t)); } -static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status) { +static void fail_scsi_op(mscd_interface_t* p_msc, uint8_t status) { msc_cbw_t const * p_cbw = &p_msc->cbw; msc_csw_t * p_csw = &p_msc->csw; + uint8_t rhport = p_msc->rhport; p_csw->status = status; p_csw->data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len; @@ -177,6 +197,32 @@ static uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) { return status; } +static bool proc_stage_status(mscd_interface_t* p_msc) { + uint8_t rhport = p_msc->rhport; + msc_cbw_t const* p_cbw = &p_msc->cbw; + // skip status if epin is currently stalled, will do it when received Clear Stall request + if (!usbd_edpt_stalled(rhport, p_msc->ep_in)) { + if ((p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir)) { + // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status + // TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); + usbd_edpt_stall(rhport, p_msc->ep_in); + } else { + TU_ASSERT(send_csw(p_msc)); + } + } + + #if TU_CHECK_MCU(OPT_MCU_CXD56) + // WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD. + // There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and + // hope everything will work + if ( usbd_edpt_stalled(rhport, p_msc->ep_in) ) { + usbd_edpt_clear_stall(rhport, p_msc->ep_in); + send_csw(p_msc); + } + #endif + return true; +} + //--------------------------------------------------------------------+ // Debug //--------------------------------------------------------------------+ @@ -219,6 +265,32 @@ static inline void set_sense_medium_not_present(uint8_t lun) { tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); } +#if CFG_TUD_MSC_ASYNC_IO +void tud_msc_async_io_done(int32_t bytes_processed) { + // Precheck to avoid queueing multiple RW done callback + TU_VERIFY(_mscd_itf.next_op != MSC_NEXT_OP_NONE,); + // Call usbd_edpt_xfer() in tud_task() to avoid racing condition + usbd_defer_func(tud_msc_async_io_done_cb, (void*) bytes_processed, false); +} + +static void tud_msc_async_io_done_cb(void* bytes_processed) { + TU_VERIFY(_mscd_itf.next_op != MSC_NEXT_OP_NONE,); + uint8_t next_op = _mscd_itf.next_op; + _mscd_itf.next_op = MSC_NEXT_OP_NONE; + int32_t nbytes = (int32_t)bytes_processed; + // READ10 + if (next_op == MSC_NEXT_OP_READ10) { + proc_read10_next(&_mscd_itf, nbytes); + } else if (next_op == MSC_NEXT_OP_WRITE10) { + proc_write10_next(&_mscd_itf, _mscd_itf.xferred_bytes, nbytes); + // Need to manually invoke CSW transfer + if (_mscd_itf.stage == MSC_STAGE_STATUS) { + proc_stage_status(&_mscd_itf); + } + } +} +#endif + //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ @@ -245,12 +317,13 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 mscd_interface_t * p_msc = &_mscd_itf; p_msc->itf_num = itf_desc->bInterfaceNumber; + p_msc->rhport = rhport; // Open endpoint pair TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0); // Prepare for Command Block Wrapper - TU_ASSERT(prepare_cbw(rhport, p_msc), drv_len); + TU_ASSERT(prepare_cbw(p_msc), drv_len); return drv_len; } @@ -289,14 +362,14 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t if (ep_addr == p_msc->ep_in) { if (p_msc->stage == MSC_STAGE_STATUS) { // resume sending SCSI status if we are in this stage previously before stalled - TU_ASSERT(send_csw(rhport, p_msc)); + TU_ASSERT(send_csw(p_msc)); } } else if (ep_addr == p_msc->ep_out) { if (p_msc->stage == MSC_STAGE_CMD) { // part of reset recovery (probably due to invalid CBW) -> prepare for new command // Note: skip if already queued previously if (usbd_edpt_ready(rhport, p_msc->ep_out)) { - TU_ASSERT(prepare_cbw(rhport, p_msc)); + TU_ASSERT(prepare_cbw(p_msc)); } } } @@ -344,7 +417,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t msc_csw_t * p_csw = &p_msc->csw; switch (p_msc->stage) { - case MSC_STAGE_CMD: + case MSC_STAGE_CMD: { //------------- new CBW received -------------// // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it if (ep_addr != p_msc->ep_out) { @@ -382,12 +455,12 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t uint8_t const status = rdwr10_validate_cmd(p_cbw); if (status != MSC_CSW_STATUS_PASSED) { - fail_scsi_op(rhport, p_msc, status); + fail_scsi_op(p_msc, status); } else if (p_cbw->total_bytes) { if (SCSI_CMD_READ_10 == p_cbw->command[0]) { - proc_read10_cmd(rhport, p_msc); + proc_read10_cmd(p_msc); } else { - proc_write10_cmd(rhport, p_msc); + proc_write10_cmd(p_msc); } } else { // no data transfer, only exist in complaint test suite @@ -400,7 +473,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t if ((p_cbw->total_bytes > 0) && !is_data_in(p_cbw->dir)) { if (p_cbw->total_bytes > CFG_TUD_MSC_EP_BUFSIZE) { TU_LOG_DRV(" SCSI reject non READ10/WRITE10 with large data\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); } else { // Didn't check for case 9 (Ho > Dn), which requires examining scsi command first // but it is OK to just receive data then responded with failed status @@ -418,12 +491,12 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t if (resplen < 0) { // unsupported command TU_LOG_DRV(" SCSI unsupported or failed command\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); } else if (resplen == 0) { if (p_cbw->total_bytes) { // 6.7 The 13 Cases: case 4 (Hi > Dn) // TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); } else { // case 1 Hn = Dn: all good p_msc->stage = MSC_STAGE_STATUS; @@ -432,7 +505,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t if (p_cbw->total_bytes == 0) { // 6.7 The 13 Cases: case 2 (Hn < Di) // TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); } else { // cannot return more than host expect p_msc->total_len = tu_min32((uint32_t)resplen, p_cbw->total_bytes); @@ -441,6 +514,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t } } } + } break; case MSC_STAGE_DATA: @@ -454,10 +528,10 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Data Stage is complete p_msc->stage = MSC_STAGE_STATUS; }else { - proc_read10_cmd(rhport, p_msc); + proc_read10_cmd(p_msc); } } else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) { - proc_write10_new_data(rhport, p_msc, xferred_bytes); + proc_write10_new_data(p_msc, xferred_bytes); } else { p_msc->xferred_len += xferred_bytes; @@ -468,7 +542,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t if ( cb_result < 0 ) { // unsupported command TU_LOG_DRV(" SCSI unsupported command\r\n"); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); }else { // TODO haven't implement this scenario any further yet } @@ -517,7 +591,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t break; } - TU_ASSERT(prepare_cbw(rhport, p_msc)); + TU_ASSERT(prepare_cbw(p_msc)); } else { // Any xfer ended here is consider unknown error, ignore it TU_LOG1(" Warning expect SCSI Status but received unknown data\r\n"); @@ -528,26 +602,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t } if (p_msc->stage == MSC_STAGE_STATUS) { - // skip status if epin is currently stalled, will do it when received Clear Stall request - if (!usbd_edpt_stalled(rhport, p_msc->ep_in)) { - if ((p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir)) { - // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status - // TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); - usbd_edpt_stall(rhport, p_msc->ep_in); - } else { - TU_ASSERT(send_csw(rhport, p_msc)); - } - } - - #if TU_CHECK_MCU(OPT_MCU_CXD56) - // WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD. - // There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and - // hope everything will work - if ( usbd_edpt_stalled(rhport, p_msc->ep_in) ) { - usbd_edpt_clear_stall(rhport, p_msc->ep_in); - send_csw(rhport, p_msc); - } - #endif + TU_ASSERT(proc_stage_status(p_msc)); } return true; @@ -751,7 +806,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ return resplen; } -static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) { +static void proc_read10_cmd(mscd_interface_t* p_msc) { msc_cbw_t const* p_cbw = &p_msc->cbw; // block size already verified not zero @@ -765,16 +820,27 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) { // Application can consume smaller bytes uint32_t const offset = p_msc->xferred_len % block_sz; - nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, (uint32_t)nbytes); +#if CFG_TUD_MSC_ASYNC_IO + p_msc->next_op = MSC_NEXT_OP_READ10; + tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, (uint32_t)nbytes); +#else + nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, (uint32_t)nbytes); + proc_read10_next(p_msc, nbytes); +#endif +} + +static void proc_read10_next(mscd_interface_t* p_msc, int32_t nbytes) { + uint8_t rhport = p_msc->rhport; if (nbytes < 0) { // negative means error -> endpoint is stalled & status in CSW set to failed TU_LOG_DRV(" tud_msc_read10_cb() return -1\r\n"); // set sense + msc_cbw_t const* p_cbw = &p_msc->cbw; set_sense_medium_not_present(p_cbw->lun); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); } else if (nbytes == 0) { // zero means not ready -> simulate an transfer complete so that this driver callback will fired again dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false); @@ -783,7 +849,7 @@ static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) { } } -static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) { +static void proc_write10_cmd(mscd_interface_t* p_msc) { msc_cbw_t const* p_cbw = &p_msc->cbw; bool writable = true; @@ -795,19 +861,19 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) { // Not writable, complete this SCSI op with error // Sense = Write protected tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); return; } // remaining bytes capped at class buffer uint16_t nbytes = (uint16_t)tu_min32(CFG_TUD_MSC_EP_BUFSIZE, p_cbw->total_bytes - p_msc->xferred_len); - // Write10 callback will be called later when usb transfer complete + uint8_t rhport = p_msc->rhport; TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, nbytes),); } // process new data arrived from WRITE10 -static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes) { +static void proc_write10_new_data(mscd_interface_t* p_msc, uint32_t xferred_bytes) { msc_cbw_t const* p_cbw = &p_msc->cbw; // block size already verified not zero @@ -818,8 +884,18 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3 // Invoke callback to consume new data uint32_t const offset = p_msc->xferred_len % block_sz; - int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, xferred_bytes); +#if CFG_TUD_MSC_ASYNC_IO + p_msc->next_op = MSC_NEXT_OP_WRITE10; + p_msc->xferred_bytes = xferred_bytes; + tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, xferred_bytes); +#else + int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, xferred_bytes); + proc_write10_next(p_msc, xferred_bytes, nbytes); +#endif +} + +static void proc_write10_next(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes) { if (nbytes < 0) { // negative means error -> failed this scsi op TU_LOG_DRV(" tud_msc_write10_cb() return -1\r\n"); @@ -828,9 +904,10 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3 p_msc->xferred_len += xferred_bytes; // Set sense + msc_cbw_t const* p_cbw = &p_msc->cbw; set_sense_medium_not_present(p_cbw->lun); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); + fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); } else { // Application consume less than what we got (including zero) if ((uint32_t)nbytes < xferred_bytes) { @@ -841,6 +918,7 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3 } // simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter + uint8_t rhport = p_msc->rhport; dcd_event_xfer_complete(rhport, p_msc->ep_out, left_over, XFER_RESULT_SUCCESS, false); } else { // Application consume all bytes in our buffer @@ -851,7 +929,7 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3 p_msc->stage = MSC_STAGE_STATUS; } else { // prepare to receive more data from host - proc_write10_cmd(rhport, p_msc); + proc_write10_cmd(p_msc); } } } diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 29acd280a..407fe241c 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -48,6 +48,11 @@ #error CFG_TUD_MSC_EP_BUFSIZE must be defined, value of a block size should work well, the more the better #endif +// Enable asynchronous read/write, once operation is finished tud_msc_async_io_done() must be called +#ifndef CFG_TUD_MSC_ASYNC_IO +#define CFG_TUD_MSC_ASYNC_IO 0 +#endif + TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); //--------------------------------------------------------------------+ @@ -73,6 +78,9 @@ bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, u // // - read < 0 : Indicate application error e.g invalid address. This request will be STALLed // and return failed status in command status wrapper phase. +// +// - In case of asynchronous IO enabled, application should passing reading parameters to background IO +// task and return immediately. Once reading is done, tud_msc_async_io_done() must be called. int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); // Invoked when received SCSI WRITE10 command @@ -88,6 +96,8 @@ int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buf // - write < 0 : Indicate application error e.g invalid address. This request will be STALLed // and return failed status in command status wrapper phase. // +// - In case of asynchronous IO enabled, application should passing writing parameters to background IO +// task and return immediately. Once writing is done, tud_msc_async_io_done() must be called. // TODO change buffer to const uint8_t* int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); @@ -121,6 +131,12 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz */ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize); +#if CFG_TUD_MSC_ASYNC_IO +// Called once asynchronous read/write operation is done +// bytes_processed has the same meaning of tud_msc_read10_cb() / +// tud_msc_write10_cb() return value +void tud_msc_async_io_done(int32_t bytes_processed); +#endif /*------------- Optional callbacks -------------*/ // Invoked when received GET_MAX_LUN request, required for multiple LUNs implementation From 04b9e203107ef5f8b9d44f9b8a302cf6504ae3ae Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 29 Jan 2025 15:20:44 +0100 Subject: [PATCH 048/382] msc_disk: fix overflow check when EP buffer size > 512. Signed-off-by: HiFiPhile --- examples/device/cdc_msc/src/msc_disk.c | 11 +++++++++-- examples/device/cdc_msc_freertos/src/msc_disk.c | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index d325d77fa..6fc0760b6 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -195,7 +195,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff } // Check for overflow of offset + bufsize - if ( offset + bufsize > DISK_BLOCK_SIZE ) { + if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) { return -1; } @@ -223,7 +223,14 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* (void) lun; // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) return -1; + if ( lba >= DISK_BLOCK_NUM ) { + return -1; + } + + // Check for overflow of offset + bufsize + if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) { + return -1; + } #ifndef CFG_EXAMPLE_MSC_READONLY uint8_t* addr = msc_disk[lba] + offset; diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index d325d77fa..6fc0760b6 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -195,7 +195,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff } // Check for overflow of offset + bufsize - if ( offset + bufsize > DISK_BLOCK_SIZE ) { + if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) { return -1; } @@ -223,7 +223,14 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* (void) lun; // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) return -1; + if ( lba >= DISK_BLOCK_NUM ) { + return -1; + } + + // Check for overflow of offset + bufsize + if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) { + return -1; + } #ifndef CFG_EXAMPLE_MSC_READONLY uint8_t* addr = msc_disk[lba] + offset; From f43100bdfd5611c2ba463a05960ea5569a53a20b Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 29 Jan 2025 15:28:19 +0100 Subject: [PATCH 049/382] cdc_msc_freertos: add async IO support. Signed-off-by: HiFiPhile --- examples/device/cdc_msc_freertos/src/main.c | 3 +- .../device/cdc_msc_freertos/src/msc_disk.c | 70 ++++++++++++++++--- .../device/cdc_msc_freertos/src/tusb_config.h | 4 ++ 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index c51e8ea81..4dada9801 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -72,7 +72,7 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; static void usb_device_task(void *param); void led_blinking_task(void* param); void cdc_task(void *params); - +extern void msc_disk_init(void); //--------------------------------------------------------------------+ // Main //--------------------------------------------------------------------+ @@ -123,6 +123,7 @@ static void usb_device_task(void *param) { board_init_after_tusb(); } + msc_disk_init(); // RTOS forever loop while (1) { // put this thread to waiting state until there is new events diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index 6fc0760b6..b0324911c 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -28,6 +28,20 @@ #if CFG_TUD_MSC +#if CFG_TUD_MSC_ASYNC_IO +// Simulate read/write operation time +#define SIM_IO_TIME_MS 20 + +TimerHandle_t sim_io_ops_timer; +static int32_t bytes_processed; +#if configSUPPORT_STATIC_ALLOCATION +StaticTimer_t sim_io_ops_timer_buf; +#endif +static void sim_io_ops_done_cb(TimerHandle_t xTimer); +#endif + +void msc_disk_init(void); + // whether host does safe-eject static bool ejected = false; @@ -119,6 +133,24 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = README_CONTENTS }; +#if CFG_TUD_MSC_ASYNC_IO +void msc_disk_init() { + +#if configSUPPORT_DYNAMIC_ALLOCATION + sim_io_ops_timer = xTimerCreate("sim_io_ops", pdMS_TO_TICKS(SIM_IO_TIME_MS), pdFALSE, NULL, sim_io_ops_done_cb); +#else + sim_io_ops_timer = xTimerCreateStatic("sim_io_ops", pdMS_TO_TICKS(SIM_IO_TIME_MS), pdFALSE, NULL, sim_io_ops_done_cb, &sim_io_ops_timer_buf); +#endif +} + +static void sim_io_ops_done_cb(TimerHandle_t xTimer) { + (void) xTimer; + tud_msc_async_io_done(bytes_processed); +} +#else +void msc_disk_init() {} +#endif + // Invoked when received SCSI_CMD_INQUIRY // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) @@ -188,21 +220,30 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { (void) lun; + int32_t ret = bufsize; // out of ramdisk if ( lba >= DISK_BLOCK_NUM ) { - return -1; + ret = -1; } // Check for overflow of offset + bufsize if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) { - return -1; + ret = -1; } - uint8_t const* addr = msc_disk[lba] + offset; - memcpy(buffer, addr, bufsize); + if (ret != -1) { + uint8_t const* addr = msc_disk[lba] + offset; + memcpy(buffer, addr, bufsize); + } - return (int32_t) bufsize; +#if CFG_TUD_MSC_ASYNC_IO + // Simulate read operation + bytes_processed = ret; + xTimerStart(sim_io_ops_timer, 0); +#endif + + return ret; } bool tud_msc_is_writable_cb (uint8_t lun) @@ -221,25 +262,34 @@ bool tud_msc_is_writable_cb (uint8_t lun) int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { (void) lun; + int32_t ret = bufsize; // out of ramdisk if ( lba >= DISK_BLOCK_NUM ) { - return -1; + ret = -1; } // Check for overflow of offset + bufsize if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) { - return -1; + ret = -1; } #ifndef CFG_EXAMPLE_MSC_READONLY - uint8_t* addr = msc_disk[lba] + offset; - memcpy(addr, buffer, bufsize); + if (ret != -1) { + uint8_t* addr = msc_disk[lba] + offset; + memcpy(addr, buffer, bufsize); + } #else (void) lba; (void) offset; (void) buffer; #endif - return (int32_t) bufsize; +#if CFG_TUD_MSC_ASYNC_IO + // Simulate read operation + bytes_processed = ret; + xTimerStart(sim_io_ops_timer, 0); +#endif + + return ret; } // Callback invoked when received an SCSI command not in built-in list below diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index c3f2f7fb5..eb4798017 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -114,6 +114,10 @@ // MSC Buffer size of Device Mass storage #define CFG_TUD_MSC_EP_BUFSIZE 512 +// Enable Async IO on MSC +#define CFG_TUD_MSC_ASYNC_IO 0 + + #ifdef __cplusplus } #endif From a40722b221f878f0d182c602f6d6db8d35031e19 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 29 Jan 2025 17:12:09 +0100 Subject: [PATCH 050/382] Enable SIM_IO_TIME_MS for normal operation. Signed-off-by: HiFiPhile --- examples/device/cdc_msc_freertos/src/msc_disk.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index b0324911c..2f3a1c30b 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -28,10 +28,10 @@ #if CFG_TUD_MSC -#if CFG_TUD_MSC_ASYNC_IO // Simulate read/write operation time -#define SIM_IO_TIME_MS 20 +#define SIM_IO_TIME_MS 0 +#if CFG_TUD_MSC_ASYNC_IO TimerHandle_t sim_io_ops_timer; static int32_t bytes_processed; #if configSUPPORT_STATIC_ALLOCATION @@ -238,9 +238,12 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff } #if CFG_TUD_MSC_ASYNC_IO - // Simulate read operation + // Simulate background read operation bytes_processed = ret; xTimerStart(sim_io_ops_timer, 0); +#elif SIM_IO_TIME_MS > 0 + // Simulate read operation + tusb_time_delay_ms_api(SIM_IO_TIME_MS); #endif return ret; @@ -284,9 +287,12 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* #endif #if CFG_TUD_MSC_ASYNC_IO - // Simulate read operation + // Simulate background write operation bytes_processed = ret; xTimerStart(sim_io_ops_timer, 0); +#elif SIM_IO_TIME_MS > 0 + // Simulate write operation + tusb_time_delay_ms_api(SIM_IO_TIME_MS); #endif return ret; From abfbcf5ccca88017dfb50e237a4981e47057b3a8 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 31 Jan 2025 11:09:35 +0100 Subject: [PATCH 051/382] Update build. Signed-off-by: HiFiPhile --- hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk | 2 +- hw/bsp/stm32h7rs/family.cmake | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk index 164452fb2..f0dfe01dc 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk @@ -12,4 +12,4 @@ SRC_C += \ $(BOARD_PATH)/tcpp0203/tcpp0203_reg.c \ INC += \ - $(BOARD_PATH)/tcpp0203 \ + $(TOP)/$(BOARD_PATH)/tcpp0203 \ diff --git a/hw/bsp/stm32h7rs/family.cmake b/hw/bsp/stm32h7rs/family.cmake index add0dc43d..d55a897ad 100644 --- a/hw/bsp/stm32h7rs/family.cmake +++ b/hw/bsp/stm32h7rs/family.cmake @@ -11,7 +11,7 @@ set(CMSIS_5 ${TOP}/lib/CMSIS_5) include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) # toolchain set up -set(CMAKE_SYSTEM_PROCESSOR cortex-m7 CACHE INTERNAL "System Processor") +set(CMAKE_SYSTEM_CPU cortex-m7 CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) set(FAMILY_MCUS STM32H7 CACHE INTERNAL "") @@ -133,15 +133,12 @@ function(family_configure_example TARGET RTOS) # Add TinyUSB target and port source family_add_tinyusb(${TARGET} OPT_MCU_STM32H7RS ${RTOS}) - target_sources(${TARGET}-tinyusb PUBLIC + target_sources(${TARGET} PUBLIC ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c ) - target_link_libraries(${TARGET}-tinyusb PUBLIC board_${BOARD}) - - # Link dependencies - target_link_libraries(${TARGET} PUBLIC board_${BOARD} ${TARGET}-tinyusb) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) # Flashing family_add_bin_hex(${TARGET}) From 84f8876c7c3639ef4ac707956831311791aefd76 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 31 Jan 2025 16:26:10 +0100 Subject: [PATCH 052/382] Use return code to choose async io. Signed-off-by: HiFiPhile --- src/class/msc/msc_device.c | 26 +++++++----------- src/class/msc/msc_device.h | 56 +++++++++++++++++++++----------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index c7c926f4e..e3fe5a078 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -78,10 +78,10 @@ typedef struct { uint8_t sense_key; uint8_t add_sense_code; uint8_t add_sense_qualifier; -#if CFG_TUD_MSC_ASYNC_IO + + // Async IO uint8_t next_op; uint32_t xferred_bytes; -#endif }mscd_interface_t; static mscd_interface_t _mscd_itf; @@ -100,9 +100,7 @@ static void proc_write10_cmd(mscd_interface_t* p_msc); static void proc_write10_new_data(mscd_interface_t* p_msc, uint32_t xferred_bytes); static void proc_write10_next(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes); static bool proc_stage_status(mscd_interface_t* p_msc); -#if CFG_TUD_MSC_ASYNC_IO static void tud_msc_async_io_done_cb(void* bytes_processed); -#endif TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) { return tu_bit_test(dir, 7); @@ -265,7 +263,6 @@ static inline void set_sense_medium_not_present(uint8_t lun) { tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); } -#if CFG_TUD_MSC_ASYNC_IO void tud_msc_async_io_done(int32_t bytes_processed) { // Precheck to avoid queueing multiple RW done callback TU_VERIFY(_mscd_itf.next_op != MSC_NEXT_OP_NONE,); @@ -289,7 +286,6 @@ static void tud_msc_async_io_done_cb(void* bytes_processed) { } } } -#endif //--------------------------------------------------------------------+ // USBD Driver API @@ -821,13 +817,12 @@ static void proc_read10_cmd(mscd_interface_t* p_msc) { // Application can consume smaller bytes uint32_t const offset = p_msc->xferred_len % block_sz; -#if CFG_TUD_MSC_ASYNC_IO p_msc->next_op = MSC_NEXT_OP_READ10; - tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, (uint32_t)nbytes); -#else nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, (uint32_t)nbytes); - proc_read10_next(p_msc, nbytes); -#endif + if (nbytes != TUD_MSC_RET_ASYNC) { + p_msc->next_op = MSC_NEXT_OP_NONE; + proc_read10_next(p_msc, nbytes); + } } static void proc_read10_next(mscd_interface_t* p_msc, int32_t nbytes) { @@ -885,14 +880,13 @@ static void proc_write10_new_data(mscd_interface_t* p_msc, uint32_t xferred_byte // Invoke callback to consume new data uint32_t const offset = p_msc->xferred_len % block_sz; -#if CFG_TUD_MSC_ASYNC_IO p_msc->next_op = MSC_NEXT_OP_WRITE10; p_msc->xferred_bytes = xferred_bytes; - tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, xferred_bytes); -#else int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, xferred_bytes); - proc_write10_next(p_msc, xferred_bytes, nbytes); -#endif + if (nbytes != TUD_MSC_RET_ASYNC) { + p_msc->next_op = MSC_NEXT_OP_NONE; + proc_write10_next(p_msc, xferred_bytes, nbytes); + } } static void proc_write10_next(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes) { diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 407fe241c..7162b11e4 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -48,10 +48,11 @@ #error CFG_TUD_MSC_EP_BUFSIZE must be defined, value of a block size should work well, the more the better #endif -// Enable asynchronous read/write, once operation is finished tud_msc_async_io_done() must be called -#ifndef CFG_TUD_MSC_ASYNC_IO -#define CFG_TUD_MSC_ASYNC_IO 0 -#endif +// Return value of callback functions +// Error +#define TUD_MSC_RET_ERROR -1 +// Asynchronous IO +#define TUD_MSC_RET_ASYNC -16 TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); @@ -62,6 +63,11 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); // Set SCSI sense response bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier); +// Called once asynchronous read/write operation is done +// bytes_processed has the same meaning of tud_msc_read10_cb() / +// tud_msc_write10_cb() return value +void tud_msc_async_io_done(int32_t bytes_processed); + //--------------------------------------------------------------------+ // Application Callbacks (WEAK is optional) //--------------------------------------------------------------------+ @@ -70,34 +76,40 @@ bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, u // - Address = lba * BLOCK_SIZE + offset // - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. // -// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. If -// - read < bufsize : These bytes are transferred first and callback invoked again for remaining data. +// - Application fill the buffer (up to bufsize) with address contents and return number of bytes read or status. // -// - read == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback invoked again with the same parameters later on. +// - ret < bufsize : These bytes are transferred first and callback will be invoked again for remaining data. // -// - read < 0 : Indicate application error e.g invalid address. This request will be STALLed +// - ret == 0 : Indicate application is not ready yet e.g disk I/O busy. +// Callback will be invoked again with the same parameters later on. +// +// - ret == TUD_MSC_RET_ERROR (-1) +// : Indicate application error e.g invalid address. This request will be STALLed // and return failed status in command status wrapper phase. // -// - In case of asynchronous IO enabled, application should passing reading parameters to background IO -// task and return immediately. Once reading is done, tud_msc_async_io_done() must be called. +// - ret == TUD_MSC_RET_ASYNC (-16) +// : Data reading will be done asynchronously in a background task. Application should return immediately. +// tud_msc_async_io_done() must be called once reading is done to signal completion. int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); // Invoked when received SCSI WRITE10 command // - Address = lba * BLOCK_SIZE + offset // - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. // -// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. If -// - write < bufsize : callback invoked again with remaining data later on. +// - Application writes data from buffer to address contents (up to bufsize) and returns the number of bytes written or status. // -// - write == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback invoked again with the same parameters later on. +// - ret < bufsize : Callback will be invoked again with remaining data later on. // -// - write < 0 : Indicate application error e.g invalid address. This request will be STALLed -// and return failed status in command status wrapper phase. +// - ret == 0 : Indicate application is not ready yet e.g disk I/O busy. +// Callback will be invoked again with the same parameters later on. // -// - In case of asynchronous IO enabled, application should passing writing parameters to background IO -// task and return immediately. Once writing is done, tud_msc_async_io_done() must be called. +// - ret == TUD_MSC_RET_ERROR (-1) +// : Indicate application error e.g invalid address. This request will be STALLed +// and return failed status in command status wrapper phase. +// +// - ret == TUD_MSC_RET_ASYNC (-16) +// : Data writing will be done asynchronously in a background task. Application should return immediately. +// tud_msc_async_io_done() must be called once writing is done to signal completion. // TODO change buffer to const uint8_t* int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); @@ -131,12 +143,6 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz */ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize); -#if CFG_TUD_MSC_ASYNC_IO -// Called once asynchronous read/write operation is done -// bytes_processed has the same meaning of tud_msc_read10_cb() / -// tud_msc_write10_cb() return value -void tud_msc_async_io_done(int32_t bytes_processed); -#endif /*------------- Optional callbacks -------------*/ // Invoked when received GET_MAX_LUN request, required for multiple LUNs implementation From 2707347decb0ea362fd0a6e4d58102c77f366429 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 31 Jan 2025 16:29:09 +0100 Subject: [PATCH 053/382] Update example. Signed-off-by: HiFiPhile --- .../device/cdc_msc_freertos/src/msc_disk.c | 126 +++++++++++------- .../device/cdc_msc_freertos/src/tusb_config.h | 6 +- 2 files changed, 79 insertions(+), 53 deletions(-) diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index 2f3a1c30b..c75b9ae34 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -28,16 +28,28 @@ #if CFG_TUD_MSC -// Simulate read/write operation time -#define SIM_IO_TIME_MS 0 +#if CFG_EXAMPLE_MSC_ASYNC_IO -#if CFG_TUD_MSC_ASYNC_IO -TimerHandle_t sim_io_ops_timer; -static int32_t bytes_processed; +#define IO_STACK_SIZE configMINIMAL_STACK_SIZE + +typedef struct { + uint8_t lun; + bool is_read; + uint32_t lba; + uint32_t offset; + void* buffer; + uint32_t bufsize; +} io_ops_t; + +QueueHandle_t io_queue; #if configSUPPORT_STATIC_ALLOCATION -StaticTimer_t sim_io_ops_timer_buf; +uint8_t io_queue_buf[sizeof(io_ops_t)]; +StaticQueue_t io_queue_static; +StackType_t io_stack[IO_STACK_SIZE]; +StaticTask_t io_taskdef; #endif -static void sim_io_ops_done_cb(TimerHandle_t xTimer); + +static void io_task(void *params); #endif void msc_disk_init(void); @@ -133,20 +145,37 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = README_CONTENTS }; -#if CFG_TUD_MSC_ASYNC_IO +#if CFG_EXAMPLE_MSC_ASYNC_IO void msc_disk_init() { -#if configSUPPORT_DYNAMIC_ALLOCATION - sim_io_ops_timer = xTimerCreate("sim_io_ops", pdMS_TO_TICKS(SIM_IO_TIME_MS), pdFALSE, NULL, sim_io_ops_done_cb); +#if configSUPPORT_STATIC_ALLOCATION + io_queue = xQueueCreateStatic(1, sizeof(io_ops_t), io_queue_buf, &io_queue_static); + xTaskCreateStatic(io_task, "io", IO_STACK_SIZE, NULL, 2, io_stack, &io_taskdef); #else - sim_io_ops_timer = xTimerCreateStatic("sim_io_ops", pdMS_TO_TICKS(SIM_IO_TIME_MS), pdFALSE, NULL, sim_io_ops_done_cb, &sim_io_ops_timer_buf); + io_queue = xQueueCreate(1, sizeof(io_ops_t)); + xTaskCreate(io_task, "io", IO_STACK_SIZE, NULL, 2, NULL); #endif } -static void sim_io_ops_done_cb(TimerHandle_t xTimer) { - (void) xTimer; - tud_msc_async_io_done(bytes_processed); +static void io_task(void *params) { + (void) params; + io_ops_t io_ops; + while (1) { + if (xQueueReceive(io_queue, &io_ops, portMAX_DELAY)) { + if (io_ops.is_read) { + uint8_t const* addr = msc_disk[io_ops.lba] + io_ops.offset; + memcpy(io_ops.buffer, addr, io_ops.bufsize); + } else { + uint8_t* addr = msc_disk[io_ops.lba] + io_ops.offset; + memcpy(addr, io_ops.buffer, io_ops.bufsize); + } + + tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); + tud_msc_async_io_done(io_ops.bufsize); + } + } } + #else void msc_disk_init() {} #endif @@ -220,33 +249,31 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { (void) lun; - int32_t ret = bufsize; // out of ramdisk if ( lba >= DISK_BLOCK_NUM ) { - ret = -1; + return TUD_MSC_RET_ERROR; } // Check for overflow of offset + bufsize if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) { - ret = -1; + return TUD_MSC_RET_ERROR; } - if (ret != -1) { - uint8_t const* addr = msc_disk[lba] + offset; - memcpy(buffer, addr, bufsize); - } +#if CFG_EXAMPLE_MSC_ASYNC_IO + io_ops_t io_ops = { .is_read = true, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize }; -#if CFG_TUD_MSC_ASYNC_IO - // Simulate background read operation - bytes_processed = ret; - xTimerStart(sim_io_ops_timer, 0); -#elif SIM_IO_TIME_MS > 0 - // Simulate read operation - tusb_time_delay_ms_api(SIM_IO_TIME_MS); + // Send IO operation to IO task + TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS); + + return TUD_MSC_RET_ASYNC; +#else + uint8_t const* addr = msc_disk[lba] + offset; + memcpy(buffer, addr, bufsize); + tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); + + return bufsize; #endif - - return ret; } bool tud_msc_is_writable_cb (uint8_t lun) @@ -264,38 +291,35 @@ bool tud_msc_is_writable_cb (uint8_t lun) // Process data in buffer to disk's storage and return number of written bytes int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { - (void) lun; - int32_t ret = bufsize; - // out of ramdisk if ( lba >= DISK_BLOCK_NUM ) { - ret = -1; + return TUD_MSC_RET_ERROR; } // Check for overflow of offset + bufsize if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) { - ret = -1; + return TUD_MSC_RET_ERROR; } -#ifndef CFG_EXAMPLE_MSC_READONLY - if (ret != -1) { - uint8_t* addr = msc_disk[lba] + offset; - memcpy(addr, buffer, bufsize); - } +#ifdef CFG_EXAMPLE_MSC_READONLY + (void) lun; (void) buffer; + return bufsize; +#endif + +#if CFG_EXAMPLE_MSC_ASYNC_IO + io_ops_t io_ops = { .is_read = false, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize }; + + // Send IO operation to IO task + TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS); + + return TUD_MSC_RET_ASYNC; #else - (void) lba; (void) offset; (void) buffer; -#endif + uint8_t* addr = msc_disk[lba] + offset; + memcpy(addr, buffer, bufsize); + tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); -#if CFG_TUD_MSC_ASYNC_IO - // Simulate background write operation - bytes_processed = ret; - xTimerStart(sim_io_ops_timer, 0); -#elif SIM_IO_TIME_MS > 0 - // Simulate write operation - tusb_time_delay_ms_api(SIM_IO_TIME_MS); + return bufsize; #endif - - return ret; } // Callback invoked when received an SCSI command not in built-in list below diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index eb4798017..d70456287 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -114,9 +114,11 @@ // MSC Buffer size of Device Mass storage #define CFG_TUD_MSC_EP_BUFSIZE 512 -// Enable Async IO on MSC -#define CFG_TUD_MSC_ASYNC_IO 0 +// Use async IO in example or not +#define CFG_EXAMPLE_MSC_ASYNC_IO 1 +// Simulate read/write operation delay +#define CFG_EXAMPLE_MSC_IO_DELAY_MS 0 #ifdef __cplusplus } From 8d2310247c47160bf8de6e5f754284360ad7e937 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 31 Jan 2025 16:31:47 +0100 Subject: [PATCH 054/382] Fix CI. Signed-off-by: HiFiPhile --- examples/device/cdc_msc_freertos/src/msc_disk.c | 2 ++ src/class/msc/msc_device.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index c75b9ae34..c2aaca847 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -166,8 +166,10 @@ static void io_task(void *params) { uint8_t const* addr = msc_disk[io_ops.lba] + io_ops.offset; memcpy(io_ops.buffer, addr, io_ops.bufsize); } else { +#ifndef CFG_EXAMPLE_MSC_READONLY uint8_t* addr = msc_disk[io_ops.lba] + io_ops.offset; memcpy(addr, io_ops.buffer, io_ops.bufsize); +#endif } tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index e3fe5a078..72c3747fc 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -267,14 +267,14 @@ void tud_msc_async_io_done(int32_t bytes_processed) { // Precheck to avoid queueing multiple RW done callback TU_VERIFY(_mscd_itf.next_op != MSC_NEXT_OP_NONE,); // Call usbd_edpt_xfer() in tud_task() to avoid racing condition - usbd_defer_func(tud_msc_async_io_done_cb, (void*) bytes_processed, false); + usbd_defer_func(tud_msc_async_io_done_cb, (void*) (intptr_t)bytes_processed, false); } static void tud_msc_async_io_done_cb(void* bytes_processed) { TU_VERIFY(_mscd_itf.next_op != MSC_NEXT_OP_NONE,); uint8_t next_op = _mscd_itf.next_op; _mscd_itf.next_op = MSC_NEXT_OP_NONE; - int32_t nbytes = (int32_t)bytes_processed; + int32_t nbytes = (int32_t)(intptr_t)bytes_processed; // READ10 if (next_op == MSC_NEXT_OP_READ10) { proc_read10_next(&_mscd_itf, nbytes); From ea38115d6c65463b8c12f2da661855d2b4f263bd Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 Feb 2025 16:43:36 +0700 Subject: [PATCH 055/382] make sure TOTAL_DRIVER_COUNT is not overflow 8-bit --- src/device/usbd.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 2a6081673..b3af84086 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -317,26 +317,24 @@ enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) }; tu_static usbd_class_driver_t const * _app_driver = NULL; tu_static uint8_t _app_driver_count = 0; -#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) +#define TOTAL_DRIVER_COUNT ((uint8_t) (_app_driver_count + BUILTIN_DRIVER_COUNT)) // virtually joins built-in and application drivers together. // Application is positioned first to allow overwriting built-in ones. TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8_t drvid) { - usbd_class_driver_t const * driver = NULL; - if ( drvid < _app_driver_count ) { + usbd_class_driver_t const *driver = NULL; + if (drvid < _app_driver_count) { // Application drivers driver = &_app_driver[drvid]; - } else if ( drvid < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0 ){ + } else if (drvid < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0) { driver = &_usbd_driver[drvid - _app_driver_count]; } return driver; } - //--------------------------------------------------------------------+ // DCD Event //--------------------------------------------------------------------+ - enum { RHPORT_INVALID = 0xFFu }; tu_static uint8_t _usbd_rhport = RHPORT_INVALID; @@ -488,6 +486,7 @@ bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Get application driver if available if (usbd_app_driver_get_cb) { _app_driver = usbd_app_driver_get_cb(&_app_driver_count); + TU_ASSERT(_app_driver_count + BUILTIN_DRIVER_COUNT <= UINT8_MAX); } // Init class drivers From 5342f1255ab92ed61018939b996e6634ffb0a833 Mon Sep 17 00:00:00 2001 From: Darian Leung <32921628+Dazza0@users.noreply.github.com> Date: Fri, 7 Mar 2025 20:39:41 +0800 Subject: [PATCH 056/382] fix: Turn various .rst files from symbolic links to proper files "code_of_conduct.rst" and "contributors.rst" both contain RST include directives, but their file types are symoblic links. This commit turns them into proper files. --- docs/contributing/code_of_conduct.rst | 0 docs/info/contributors.rst | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 120000 => 100644 docs/contributing/code_of_conduct.rst mode change 120000 => 100644 docs/info/contributors.rst diff --git a/docs/contributing/code_of_conduct.rst b/docs/contributing/code_of_conduct.rst deleted file mode 120000 index fb1859c75..000000000 --- a/docs/contributing/code_of_conduct.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../CODE_OF_CONDUCT.rst \ No newline at end of file diff --git a/docs/contributing/code_of_conduct.rst b/docs/contributing/code_of_conduct.rst new file mode 100644 index 000000000..fb1859c75 --- /dev/null +++ b/docs/contributing/code_of_conduct.rst @@ -0,0 +1 @@ +.. include:: ../../CODE_OF_CONDUCT.rst \ No newline at end of file diff --git a/docs/info/contributors.rst b/docs/info/contributors.rst deleted file mode 120000 index 35e0b05f5..000000000 --- a/docs/info/contributors.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../CONTRIBUTORS.rst \ No newline at end of file diff --git a/docs/info/contributors.rst b/docs/info/contributors.rst new file mode 100644 index 000000000..35e0b05f5 --- /dev/null +++ b/docs/info/contributors.rst @@ -0,0 +1 @@ +.. include:: ../../CONTRIBUTORS.rst \ No newline at end of file From 8f288e96a85c7f4a073338c47107af2770c3dcaf Mon Sep 17 00:00:00 2001 From: Darian Leung <32921628+Dazza0@users.noreply.github.com> Date: Fri, 7 Mar 2025 21:17:18 +0800 Subject: [PATCH 057/382] refactor: Fix inline literal and code blocks in .rst documents - Added missing inline literals (double backticks) to any reference of symbol names and macros - Added language specifier to "code-block" directives to enable syntax highlighting when rendered. --- README.rst | 13 +- docs/contributing/porting.rst | 120 ++++++----- docs/info/changelog.rst | 334 ++++++++++++++--------------- docs/reference/getting_started.rst | 76 +++---- 4 files changed, 271 insertions(+), 272 deletions(-) diff --git a/README.rst b/README.rst index e4ad91e47..efbfa354b 100644 --- a/README.rst +++ b/README.rst @@ -15,10 +15,7 @@ TinyUSB Project .. figure:: docs/assets/logo.svg :alt: TinyUSB -TinyUSB is an open-source cross-platform USB Host/Device stack for -embedded system, designed to be memory-safe with no dynamic allocation -and thread-safe with all interrupt events are deferred then handled in -the non-ISR task function. Check out the online `documentation `__ for more details. +TinyUSB is an open-source cross-platform USB Host/Device stack for embedded system, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events are deferred then handled in the non-ISR task function. Check out the online `documentation `__ for more details. .. figure:: docs/assets/stack.svg :width: 500px @@ -32,7 +29,7 @@ the non-ISR task function. Check out the online `documentation `_ for information about using TinyUSB and how it is implemented. -Check out `Getting Started`_ guide for adding TinyUSB to your project or building the examples. If you are new to TinyUSB, we recommend starting with the `cdc_msc` example. There is a handful of `Supported Boards`_ that should work out of the box. +Check out `Getting Started`_ guide for adding TinyUSB to your project or building the examples. If you are new to TinyUSB, we recommend starting with the ``cdc_msc`` example. There is a handful of `Supported Boards`_ that should work out of the box. We use `GitHub Discussions `_ as our forum. It is a great place to ask questions and advice from the community or to discuss your TinyUSB-based projects. @@ -69,7 +66,7 @@ Supports multiple device configurations by dynamically changing USB descriptors, - Vendor-specific class support with generic In & Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file. - `WebUSB `__ with vendor-specific class -If you have a special requirement, `usbd_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. Here is how the RPi team added their reset interface `raspberrypi/pico-sdk#197 `_ +If you have a special requirement, ``usbd_app_driver_get_cb()`` can be used to write your own class driver without modifying the stack. Here is how the RPi team added their reset interface `raspberrypi/pico-sdk#197 `_ Host Stack ========== @@ -80,7 +77,7 @@ Host Stack - Vendor serial over USB: FTDI, CP210x, CH34x - Hub with multiple-level support -Similar to the Device Stack, if you have a special requirement, `usbh_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. +Similar to the Device Stack, if you have a special requirement, ``usbh_app_driver_get_cb()`` can be used to write your own class driver without modifying the stack. Power Delivery Stack ==================== diff --git a/docs/contributing/porting.rst b/docs/contributing/porting.rst index f81d98782..c3076354c 100644 --- a/docs/contributing/porting.rst +++ b/docs/contributing/porting.rst @@ -9,7 +9,7 @@ data transactions on different endpoints. Porting is the process of adding low-l the rest of the common stack. Once the low-level is implemented, it is very easy to add USB support for the microcontroller to other projects, especially those already using TinyUSB such as CircuitPython. -Below are instructions on how to get the cdc_msc device example running on a new microcontroller. Doing so includes adding the common code necessary for other uses while minimizing other extra code. Whenever you see a phrase or word in <> it should be replaced. +Below are instructions on how to get the cdc_msc device example running on a new microcontroller. Doing so includes adding the common code necessary for other uses while minimizing other extra code. Whenever you see a phrase or word in ``<>`` it should be replaced. Register defs ------------- @@ -18,25 +18,27 @@ The first step to adding support is including the register definitions and start microcontroller in TinyUSB. We write the TinyUSB implementation against these structs instead of higher level functions to keep the code small and to prevent function name collisions in linking of larger projects. For ARM microcontrollers this is the CMSIS definitions. They should be placed in the ``hw/mcu//`` directory. -Once this is done, create a directory in ``hw/bsp/`` for the specific board you are using to test the code. (Duplicating an existing board's directory is the best way to get started.) The board should be a readily available development board so that others can also test. +Once this is done, create a directory in ``hw/bsp/`` for the specific board you are using to test the code (duplicating an existing board's directory is the best way to get started). The board should be a readily available development board so that others can also test. Build ----- Now that those directories are in place, we can start our iteration process to get the example building successfully. To build, run from the root of TinyUSB: -``make -C examples/device/cdc_msc BOARD=`` +.. code-block:: bash -Unless, you've read ahead, this will fail miserably. Now, lets get it to fail less by updating the files in the board directory. The code in the board's directory is responsible for setting up the microcontroller's clocks and pins so that USB works. TinyUSB itself only operates on the USB peripheral. The board directory also includes information what files are needed to build the example. + make -C examples/device/cdc_msc BOARD= -One of the first things to change is the ``-DCFG_TUSB_MCU`` cflag in the ``board.mk`` file. This is used to tell TinyUSB what platform is being built. So, add an entry to ``src/tusb_option.h`` and update the CFLAG to match. +Unless you've read ahead, this will fail miserably. Now, lets get it to fail less by updating the files in the board directory. The code in the board's directory is responsible for setting up the microcontroller's clocks and pins so that USB works. TinyUSB itself only operates on the USB peripheral. The board directory also includes information what files are needed to build the example. -Update ``board.mk``\ 's VENDOR and CHIP_FAMILY values when creating the directory for the struct files. Duplicate one of the other sources from ``src/portable`` into ``src/portable//`` and delete all of the implementation internals. We'll cover what everything there does later. For now, get it compiling. +One of the first things to change is the ``-DCFG_TUSB_MCU`` C flag in the ``board.mk`` file. This is used to tell TinyUSB what platform is being built. So, add an entry to ``src/tusb_option.h`` and update the ``CFLAGS`` to match. + +Update ``board.mk``'s VENDOR and CHIP_FAMILY values when creating the directory for the struct files. Duplicate one of the other sources from ``src/portable`` into ``src/portable//`` and delete all of the implementation internals. We'll cover what everything there does later. For now, get it compiling. Implementation -------------- -At this point you should get an error due to an implementation issue and hopefully the build is setup for the new MCU. You will still need to modify the ``board.mk`` to include specific CFLAGS, the linker script, linker flags, source files, include directories. All file paths are relative to the top of the TinyUSB repo. +At this point you should get an error due to an implementation issue and hopefully the build is setup for the new MCU. You will still need to modify the ``board.mk`` to include specific ``CFLAGS``, the linker script, linker flags, source files, include directories. All file paths are relative to the top of the TinyUSB repo. Board Support (BSP) ^^^^^^^^^^^^^^^^^^^ @@ -45,17 +47,17 @@ The board support code is only used for self-contained examples and testing. It It is located in ``hw/bsp//board_.c``. -board_init -~~~~~~~~~~ +``board_init()`` +~~~~~~~~~~~~~~~~ -``board_init`` is responsible for starting the MCU, setting up the USB clock and USB pins. It is also responsible for initializing LED pins. +``board_init()`` is responsible for starting the MCU, setting up the USB clock and USB pins. It is also responsible for initializing LED pins. One useful clock debugging technique is to set up a PWM output at a known value such as 500hz based on the USB clock so that you can verify it is correct with a logic probe or oscilloscope. Setup your USB in a crystal-less mode when available. That makes the code easier to port across boards. -board_led_write -~~~~~~~~~~~~~~~ +``board_led_write()`` +~~~~~~~~~~~~~~~~~~~~~ Feel free to skip this until you want to verify your demo code is running. To implement, set the pin corresponding to the led to output a value that lights the LED when ``state`` is true. @@ -64,48 +66,48 @@ OS Abstraction Layer (OSAL) The OS Abstraction Layer is responsible for providing basic data structures for TinyUSB that may allow for concurrency when used with an RTOS. Without an RTOS it simply handles concurrency issues between the main code and interrupts. The code is almost entirely agnostic of MCU and lives in ``src/osal``. -In RTOS configurations, tud_task()/tuh_task() blocks behind a synchronization structure when the event queue is empty, so that the scheduler may give the CPU to a different task. To take advantage of the library's capability to yield the CPU when there are no actionable USB device events, ensure that the `CFG_TUSB_OS` symbol is defined, e.g `OPT_OS_FREERTOS` enables the FreeRTOS scheduler to schedule other threads than that which calls `tud_task()/tuh_task()`. +In RTOS configurations, ``tud_task()``/``tuh_task()`` blocks behind a synchronization structure when the event queue is empty, so that the scheduler may give the CPU to a different task. To take advantage of the library's capability to yield the CPU when there are no actionable USB device events, ensure that the ``CFG_TUSB_OS`` symbol is defined, e.g ``OPT_OS_FREERTOS`` enables the FreeRTOS scheduler to schedule other threads than that which calls ``tud_task()``/``tuh_task()``. Device API ^^^^^^^^^^ -After the USB device is setup, the USB device code works by processing events on the main thread (by calling ``tud_task``\ ). These events are queued by the USB interrupt handler. So, there are three parts to the device low-level API: device setup, endpoint setup and interrupt processing. +After the USB device is setup, the USB device code works by processing events on the main thread (by calling ``tud_task()``). These events are queued by the USB interrupt handler. So, there are three parts to the device low-level API: device setup, endpoint setup and interrupt processing. All of the code for the low-level device API is in ``src/portable///dcd_.c``. Device Setup ~~~~~~~~~~~~ -dcd_init -"""""""" +``dcd_init()`` +"""""""""""""" Initializes the USB peripheral for device mode and enables it. This function should enable internal D+/D- pull-up for enumeration. -dcd_int_enable / dcd_int_disable -"""""""""""""""""""""""""""""""" +``dcd_int_enable()`` / ``dcd_int_disable()`` +"""""""""""""""""""""""""""""""""""""""""""" Enables or disables the USB device interrupt(s). May be used to prevent concurrency issues when mutating data structures shared between main code and the interrupt handler. -dcd_int_handler -""""""""""""""" +``dcd_int_handler()`` +""""""""""""""""""""" Processes all the hardware generated events e.g Bus reset, new data packet from host etc ... It will be called by application in the MCU USB interrupt handler. -dcd_set_address -""""""""""""""" +``dcd_set_address()`` +""""""""""""""""""""" Called when the device is given a new bus address. If your peripheral automatically changes address during enumeration (like the nrf52) you may leave this empty and also no queue an event for the corresponding SETUP packet. -dcd_remote_wakeup -""""""""""""""""" +``dcd_remote_wakeup()`` +""""""""""""""""""""""" Called to remote wake up host when suspended (e.g hid keyboard) -dcd_connect / dcd_disconnect -"""""""""""""""""""""""""""" +``dcd_connect()`` / ``dcd_disconnect()`` +"""""""""""""""""""""""""""""""""""""""" Connect or disconnect the data-line pull-up resistor. Define only if MCU has an internal pull-up. (BSP may define for MCU without internal pull-up.) @@ -114,8 +116,8 @@ Special events You must let TinyUSB know when certain events occur so that it can continue its work. There are a few methods you can call to queue events for TinyUSB to process. -dcd_event_bus_signal -"""""""""""""""""""" +``dcd_event_bus_signal()`` +"""""""""""""""""""""""""" There are a number of events that your peripheral may communicate about the state of the bus. Here is an overview of what they are. Events in **BOLD** must be provided for TinyUSB to work. @@ -125,51 +127,51 @@ There are a number of events that your peripheral may communicate about the stat Calls to this look like: -.. code-block:: +.. code-block:: c dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); -The first ``0`` is the USB peripheral number. Statically saying 0 is common for single USB device MCUs. +The first ``0`` is the USB peripheral number. Statically saying ``0`` is common for single USB device MCUs. The ``true`` indicates the call is from an interrupt handler and will always be the case when porting in this way. -dcd_setup_received -"""""""""""""""""" +``dcd_setup_received()`` +"""""""""""""""""""""""" SETUP packets are a special type of transaction that can occur at any time on the control endpoint, numbered ``0``. Since they are unique, most peripherals have special handling for them. Their data is always 8 bytes in length as well. Calls to this look like: -.. code-block:: +.. code-block:: c dcd_event_setup_received(0, setup, true); -As before with ``dcd_event_bus_signal`` the first argument is the USB peripheral number and the third is true to signal its being called from an interrupt handler. The middle argument is byte array of length 8 with the contents of the SETUP packet. It can be stack allocated because it is copied into the queue. +As before with ``dcd_event_bus_signal()`` the first argument is the USB peripheral number and the third is true to signal its being called from an interrupt handler. The middle argument is byte array of length 8 with the contents of the SETUP packet. It can be stack allocated because it is copied into the queue. Endpoints ~~~~~~~~~ Endpoints are the core of the USB data transfer process. They come in a few forms such as control, isochronous, bulk, and interrupt. We won't cover the details here except with some caveats in open below. In general, data is transferred by setting up a buffer of a given length to be transferred on a given endpoint address and then waiting for an interrupt to signal that the transfer is finished. Further details below. -Endpoints within USB have an address which encodes both the number and direction of an endpoint. TinyUSB provides ``tu_edpt_number`` and ``tu_edpt_dir`` to unpack this data from the address. Here is a snippet that does it. +Endpoints within USB have an address which encodes both the number and direction of an endpoint. TinyUSB provides ``tu_edpt_number()`` and ``tu_edpt_dir()`` to unpack this data from the address. Here is a snippet that does it. -.. code-block:: +.. code-block:: c uint8_t epnum = tu_edpt_number(ep_addr); uint8_t dir = tu_edpt_dir(ep_addr); -dcd_edpt_open -""""""""""""" +``dcd_edpt_open()`` +""""""""""""""""""" Opening an endpoint is done for all non-control endpoints once the host picks a configuration that the device should use. At this point, the endpoint should be enabled in the peripheral and configured to match the endpoint descriptor. Pay special attention to the direction of the endpoint you can get from the helper methods above. It will likely change what registers you are setting. Also make sure to enable endpoint specific interrupts. -dcd_edpt_close -"""""""""""""" +``dcd_edpt_close()`` +"""""""""""""""""""" Close an endpoint. his function is used for implementing alternate settings. @@ -177,10 +179,10 @@ After calling this, the device should not respond to any packets directed toward Implementation is optional. Must be called from the USB task. Interrupts could be disabled or enabled during the call. -dcd_edpt_xfer -""""""""""""" +``dcd_edpt_xfer()`` +""""""""""""""""""" -``dcd_edpt_xfer`` is responsible for configuring the peripheral to send or receive data from the host. "xfer" is short for "transfer". **This is one of the core methods you must implement for TinyUSB to work (one other is the interrupt handler).** Data from the host is the OUT direction and data to the host is IN. It is used for all endpoints including the control endpoint 0. Make sure to handle the zero-length packet STATUS packet on endpoint 0 correctly. It may be a special transaction to the peripheral. +``dcd_edpt_xfer()`` is responsible for configuring the peripheral to send or receive data from the host. "xfer" is short for "transfer". **This is one of the core methods you must implement for TinyUSB to work (one other is the interrupt handler).** Data from the host is the OUT direction and data to the host is IN. It is used for all endpoints including the control endpoint 0. Make sure to handle the zero-length packet STATUS packet on endpoint 0 correctly. It may be a special transaction to the peripheral. Besides that, all other transactions are relatively straight-forward. The endpoint address provides the endpoint number and direction which usually determines where to write the buffer info. The buffer and its length are usually @@ -195,21 +197,21 @@ Others (like the nRF52) may need each USB packet queued individually. To make th some state for yourself and queue up an intermediate USB packet from the interrupt handler. Once the transaction is going, the interrupt handler will notify TinyUSB of transfer completion. -During transmission, the IN data buffer is guaranteed to remain unchanged in memory until the ``dcd_xfer_complete`` function is called. +During transmission, the IN data buffer is guaranteed to remain unchanged in memory until the ``dcd_xfer_complete()`` function is called. -The dcd_edpt_xfer function must never add zero-length-packets (ZLP) on its own to a transfer. If a ZLP is required, -then it must be explicitly sent by the stack calling dcd_edpt_xfer(), by calling dcd_edpt_xfer() a second time with len=0. +The ``dcd_edpt_xfer()`` function must never add zero-length-packets (ZLP) on its own to a transfer. If a ZLP is required, +then it must be explicitly sent by the stack calling ``dcd_edpt_xfer()``, by calling ``dcd_edpt_xfer()`` a second time with len=0. For control transfers, this is automatically done in ``usbd_control.c``. -At the moment, only a single buffer can be transmitted at once. There is no provision for double-buffering. new dcd_edpt_xfer() will not -be called again on the same endpoint address until the driver calls dcd_xfer_complete() (except in cases of USB resets). +At the moment, only a single buffer can be transmitted at once. There is no provision for double-buffering. new ``dcd_edpt_xfer()`` will not +be called again on the same endpoint address until the driver calls ``dcd_xfer_complete()`` (except in cases of USB resets). -dcd_xfer_complete -""""""""""""""""" +``dcd_xfer_complete()`` +""""""""""""""""""""""" -Once a transfer completes you must call dcd_xfer_complete from the USB interrupt handler to let TinyUSB know that a transaction has completed. Here is a sample call: +Once a transfer completes you must call ``dcd_xfer_complete()`` from the USB interrupt handler to let TinyUSB know that a transaction has completed. Here is a sample call: -.. code-block:: +.. code-block:: c dcd_event_xfer_complete(0, ep_addr, xfer->actual_len, XFER_RESULT_SUCCESS, true); @@ -219,23 +221,23 @@ The arguments are: * the USB peripheral number * the endpoint address -* the actual length of the transfer. (OUT transfers may be smaller than the buffer given in ``dcd_edpt_xfer``\ ) +* the actual length of the transfer. (OUT transfers may be smaller than the buffer given in ``dcd_edpt_xfer()``) * the result of the transfer. Failure isn't handled yet. * ``true`` to note the call is from an interrupt handler. -dcd_edpt_stall / dcd_edpt_clear_stall -""""""""""""""""""""""""""""""""""""" +``dcd_edpt_stall()`` / ``dcd_edpt_clear_stall()`` +""""""""""""""""""""""""""""""""""""""""""""""""" -Stalling is one way an endpoint can indicate failure such as when an unsupported command is transmitted. The pair of ``dcd_edpt_stall``\ , ``dcd_edpt_clear_stall`` help manage the stall state of all endpoints. +Stalling is one way an endpoint can indicate failure such as when an unsupported command is transmitted. The pair of ``dcd_edpt_stall()``, ``dcd_edpt_clear_stall()`` help manage the stall state of all endpoints. Woohoo! ------- -At this point you should have everything working! ;-) Of course, you may not write perfect code. Here are some tips and tricks for debugging. +At this point you should have everything working! 🙂 Of course, you may not write perfect code. Here are some tips and tricks for debugging. Use `WireShark `_ or `a Beagle `_ to sniff the USB traffic. When things aren't working its likely very early in the USB enumeration process. Figuring out where can help clue in where the issue is. For example: * If the host sends a SETUP packet and its not ACKed then your USB peripheral probably isn't started correctly. -* If the peripheral is started correctly but it still didn't work, then verify your usb clock is correct. (You did output a PWM based on it right? ;-) ) -* If the SETUP packet is ACKed but nothing is sent back then you interrupt handler isn't queueing the setup packet correctly. (Also, if you are using your own code instead of an example ``tud_task`` may not be called.) If that's OK, the ``dcd_xfer_complete`` may not be setting up the next transaction correctly. +* If the peripheral is started correctly but it still didn't work, then verify your usb clock is correct. (You did output a PWM based on it right? 🙂) +* If the SETUP packet is ACKed but nothing is sent back then you interrupt handler isn't queueing the setup packet correctly. (Also, if you are using your own code instead of an example ``tud_task()`` may not be called.) If that's OK, the ``dcd_xfer_complete()`` may not be setting up the next transaction correctly. diff --git a/docs/info/changelog.rst b/docs/info/changelog.rst index 0a34c0842..6024bb9e3 100644 --- a/docs/info/changelog.rst +++ b/docs/info/changelog.rst @@ -15,12 +15,12 @@ General - Better support dcache, make sure all usb-transferred buffer are cache line aligned and occupy full cache line - Build ARM IAR with CircleCI -- Improve HIL with dual/host_info_to_device_cdc optional for pico/pico2, enable dwc2 dma test +- Improve HIL with `dual/host_info_to_device_cdc`` optional for pico/pico2, enable dwc2 dma test API Changes ----------- -- Change signature of ``tusb_init(rhport, tusb_rhport_init_t*)``, tusb_init(void) is now deprecated but still available for backward compatibility +- Change signature of ``tusb_init(rhport, tusb_rhport_init_t*)``, ``tusb_init(void)`` is now deprecated but still available for backward compatibility - Add new ``tusb_int_handler(rhport, in_isr)`` - Add time-related APIs: ``tusb_time_millis_api()`` and ``tusb_time_delay_ms_api()`` for non-RTOS, required for some ports/configuration - New configuration macros: @@ -37,17 +37,17 @@ Controller Driver (DCD & HCD) - Add DMA support for both device and host controller - Add host driver support including: full/high speed, control/bulk/interrupt (CBI) transfer, split CBI i.e FS/LS attached via highspeed hub, hub support -- RP2: implement dcd_edpt_iso_alloc() and dcd_edpt_iso_activate() for isochronous endpoint +- RP2: implement ``dcd_edpt_iso_alloc()`` and ``dcd_edpt_iso_activate()`` for isochronous endpoint - iMXRT1170 support M4 core Device Stack ------------ - Vendor Fix class reset -- NCM fix recursions in tud_network_recv_renew() -- Audio fix align issue of _audiod_fct.alt_setting +- NCM fix recursions in ``tud_network_recv_renew()`` +- Audio fix align issue of ``_audiod_fct.alt_setting`` - UVC support format frame based -- Change dcd_dcache_() return type from void to bool +- Change ``dcd_dcache_()`` return type from void to bool - HID add Usage Table for Physical Input Device Page (0x0F) Host Stack @@ -89,20 +89,20 @@ Controller Driver (DCD & HCD) - Add support for ch32 usbd e.g ch32v203 - Add support for STM32G4 and STM32U5 microcontrollers. - Fix h5 (32-bit) errata 2.15.1: Buffer description table update completes after CTR interrupt triggers - - ISO EP buffer allocation improvements, implement dcd_edpt_close_all() + - ISO EP buffer allocation improvements, implement ``dcd_edpt_close_all()`` - Fix ch32v203 race condition and stability issue with - fix ch32v203 seems to unconditionally accept ZLP on EP0 OUT. - fix v203 race condition between rx bufsize and RX_STAT which cause PMAOVR, occurs with WRITE10 - - correctly handle setup prepare at dcd_edpt0_status_complete(), which fixes the race condition with windows where we could miss setup packet (setup bit set, but count = 0) + - correctly handle setup prepare at ``dcd_edpt0_status_complete()``, which fixes the race condition with windows where we could miss setup packet (setup bit set, but count = 0) - MAX3421E - Add support for rp2040, esp32 (c3, c6, h2, etc..) - - Add hcd_deinit() for max3421 + - Add ``hcd_deinit()`` for max3421 - Retry NAK handling next frame to reduce CPU and SPI bus usage - - add cpuctl and pinctl to tuh_configure() option for max3421 + - add ``cpuctl`` and ``pinctl`` to ``tuh_configure()`` option for max3421 - Implement hcd abort transfer for Max3421 - Properly Handle NAK Response in MAX3421E driver: correctly switch and skip writing to 2 FIFOs when NAK received. Otherwise, the driver may hang in certain conditions. @@ -114,7 +114,7 @@ Controller Driver (DCD & HCD) - nRF - - Fix dcd_edpt_open for iso endpoint + - Fix ``dcd_edpt_open()`` for iso endpoint - Handle ISOOUT CRC errors - Add compile support with old nordic sdk - Fix a few race conditions @@ -141,7 +141,7 @@ Controller Driver (DCD & HCD) Device Stack ------------ -- Add tud_deinit() and class driver deinit() to deinitialize TinyUSB device stack. +- Add ``tud_deinit()`` and ``class driver deinit()`` to deinitialize TinyUSB device stack. - Add support for generic SOF callback. - Add set address recovery time 2ms per USB spec. @@ -157,7 +157,7 @@ Device Stack - CDC - - Add tud_cdc_configure_fifo() to make RX/TX buffer persistent (not clear when disconnected) + - Add ``tud_cdc_configure_fifo()`` to make RX/TX buffer persistent (not clear when disconnected) - Add missing capability bit for CDC ACM serial break support - Enhanced CDC class with better handling of large data transmissions. - Add missing capability bit for CDC ACM serial break support @@ -175,39 +175,39 @@ Device Stack - Net - Rewrite of NCM device driver to improve throughput - - removed obsolete tud_network_link_state_cb() + - removed obsolete ``tud_network_link_state_cb()`` - USBTMC Added notification support - Vendor - Migrate to new endpoint stream API, support non-buffered TX/RX - - Add ZLP for write() when needed + - Add ZLP for ``write()`` when needed - Video - Enhance UVC descriptors and example - Video Added support for USB Video Class (UVC) with MJPEG. - Fix multiple interfaces, add an example of 2ch video capture. - - Fix race for tud_video_n_streaming check + - Fix race for ``tud_video_n_streaming()`` check Host Stack ---------- -- Added tuh_deinit() to de-initialize TinyUSB host stack. +- Added ``tuh_deinit()`` to de-initialize TinyUSB host stack. - Added support for new USB mass storage class APIs. - Improved error handling and retry mechanisms for unstable devices. - CDC Serial - Add support for ch34x - - Allow to overwrite CFG_TUH_CDC_FTDI/CP210X/CH32X_VID_PID_LIST + - Allow to overwrite ``CFG_TUH_CDC_FTDI/CP210X/CH32X_VID_PID_LIST`` - Enhanced stability of CDC-ACM devices during enumeration. - HID - - Add tuh_hid_receive_abort() - - Add tuh_hid_get_report() + - Add ``tuh_hid_receive_abort()`` + - Add ``tuh_hid_get_report()`` - Hub @@ -224,14 +224,14 @@ Host Stack - Remove submodules and use python script to manage repo dependencies #1947 - Add CMake support for most families and boards, move build file from tools/ to examples/build_system - Add ETM trace support with JTrace for nrf52840, nrf5340, mcb1857, stm32h743eval, ra6m5 -- [osal] Make it possible to override the osal_task_delay() in osal_none +- [osal] Make it possible to override the ``osal_task_delay()`` in osal_none - Add CDC+UAC2 composite device example - Enhance Hardware-in-the-loop (HIL) testing with more boards: rp2040, stm32l412nucleo, stm32f746disco, lpcxpresso43s67 Controller Driver (DCD & HCD) ----------------------------- -- Add new ISO endpoint API: dcd_edpt_iso_alloc() and dcd_edpt_iso_activate() +- Add new ISO endpoint API: ``dcd_edpt_iso_alloc()`` and ``dcd_edpt_iso_activate()`` - Remove legacy driver st/synopsys - EHCI @@ -244,10 +244,10 @@ Controller Driver (DCD & HCD) - Fix error on EHCI causes xfer error in non-queued qhd which cause memory fault - Un-roll recursive hub removal with usbh queue - Fix issue when removing queue head - - Implement hcd_edpt_abort_xfer() + - Implement ``hcd_edpt_abort_xfer()`` - use standard USB complete interrupt instead of custom chipidea async/period interrupt to be more compatible with other ehci implementation - refactor usb complete & error isr processing, merge, update. Fix EHCI QHD reuses QTD on wrong endpoint - - Improve bus reset, fix send_setup() not carried out if halted previously + - Improve bus reset, fix ``send_setup()`` not carried out if halted previously - Fix clear qhd halted bit if not caused by STALL protocol to allow for next transfer - ChipIdea Highspeed @@ -273,12 +273,12 @@ Controller Driver (DCD & HCD) - rp2040 - [dcd] Make writes to SIE_CTRL aware of concurrent access - - [hcd] add hcd_frame_number(), hcd_edpt_abort_xfer() for pio-usb host + - [hcd] add ``hcd_frame_number()``, ``hcd_edpt_abort_xfer()`` for pio-usb host - stm32 fsdev: - Add STM32L5 support - - Implement dcd_edpt_iso_alloc() and dcd_edpt_iso_activate() + - Implement ``dcd_edpt_iso_alloc()`` and ``dcd_edpt_iso_activate()`` - OHCI @@ -292,7 +292,7 @@ Controller Driver (DCD & HCD) Device Stack ------------ -- Add optional hooks tud_event_hook_cb() +- Add optional hooks ``tud_event_hook_cb()`` - Audio (UAC2) - Fix feedback EP buffer alignment. @@ -310,12 +310,12 @@ Device Stack - MIDI - - Fix stream_write() always writes system messages to cable 0 + - Fix ``stream_write()`` always writes system messages to cable 0 - Fix incorrect NOTE_ON, NOTE_OFF definitions - USBTMC: Fix tmc488 bit order -- Vendor: fix read()/write() race condition +- Vendor: fix ``read()``/``write()`` race condition - Video (UVC) @@ -326,26 +326,26 @@ Host Stack - USBH - - Add new APIs: tuh_interface_set(), tuh_task_event_ready(), tuh_edpt_abort_xfer(), tuh_rhport_reset_bus(), tuh_rhport_is_active() + - Add new APIs: ``tuh_interface_set()``, ``tuh_task_event_ready()``, ``tuh_edpt_abort_xfer()``, ``tuh_rhport_reset_bus()``, ``tuh_rhport_is_active()`` - Fix issue when device generate multiple attach/detach/attach when plugging in - Prefer application callback over built-in driver on transfer complete event - - Correct hcd_edpt_clear_stall() API signature + - Correct ``hcd_edpt_clear_stall()`` API signature - Separate bus reset delay and contact debouncing delay in enumeration - - Support usbh_app_driver_get_cb() for application drivers + - Support ``usbh_app_driver_get_cb()`` for application drivers - Fix usbh enumeration removal race condition - - Add optional hooks tuh_event_hook_cb() + - Add optional hooks ``tuh_event_hook_cb()`` - CDC - - Breaking: change tuh_cdc_itf_get_info() to use tuh_itf_info_t instead of tuh_cdc_info_t + - Breaking: change ``tuh_cdc_itf_get_info()`` to use tuh_itf_info_t instead of tuh_cdc_info_t - Fix cdc host enumeration issue when device does not support line request - Add support for vendor usb2uart serial: ftdi, cp210x, ch9102f - - Improve sync control API e.g tuh_cdc_set_control_line_state(), tuh_cdc_set_line_coding() + - Improve sync control API e.g ``tuh_cdc_set_control_line_state()``, ``tuh_cdc_set_line_coding()`` - HID - - Add new APIs tuh_hid_send_report(), tuh_hid_itf_get_info(), tuh_hid_receive_ready(), tuh_hid_send_ready(), tuh_hid_set_default_protocol() - - Change meaning of CFG_TUH_HID to total number of HID interfaces supported. Previously CFG_TUH_HID is max number of interfaces per device which is rather limited and consume more resources than needed. + - Add new APIs ``tuh_hid_send_report()``, ``tuh_hid_itf_get_info()``, ``tuh_hid_receive_ready()``, ``tuh_hid_send_ready()``, ``tuh_hid_set_default_protocol()`` + - Change meaning of CFG_TUH_HID to total number of HID interfaces supported. Previously ``CFG_TUH_HID`` is max number of interfaces per device which is rather limited and consume more resources than needed. - HUB @@ -354,7 +354,7 @@ Host Stack - MSC - - Fix bug in tuh_msc_ready() + - Fix bug in ``tuh_msc_ready()`` - Fix host msc get maxlun not using aligned section memory 0.15.0 @@ -385,7 +385,7 @@ Controller Driver (DCD & HCD) - [rp2040] - [dcd] Implement workaround for Errata 15. This enable SOF when bulk-in endpoint is in use and reduce its bandwidth to only 80% - - [hcd] Fix shared irq slots filling up when hcd_init() is called multiple times + - [hcd] Fix shared irq slots filling up when ``hcd_init()`` is called multiple times - [hcd] Support host bulk endpoint using hw "interrupt" endpoint. Note speed limit is 64KB/s - [samd][dcd] Add support for ISO endpoint @@ -410,12 +410,12 @@ Device Stack - [HID] - Add FIDO descriptor template - - change length in tud_hid_report_complete_cb() from uint8 to uint16 + - change length in ``tud_hid_report_complete_cb()`` from ``uint8_t`` to ``uint16_t`` - [CDC] - Fix autoflush for FIFO < MPS - - Fix tx fifo memory overflown when DTR is not set and tud_cdc_write() is called repeatedly with large enough data + - Fix tx fifo memory overflown when DTR is not set and ``tud_cdc_write()`` is called repeatedly with large enough data - [USBTMC] Fix packet size with highspeed @@ -423,7 +423,7 @@ Host Stack ---------- - Retry a few times with transfers in enumeration since device can be unstable when starting up -- [MSC] Rework host masstorage API. Add new **host/msc_file_explorer** example +- [MSC] Rework host masstorage API. Add new ``host/msc_file_explorer`` example - [CDC] - Add support for host cdc @@ -433,22 +433,22 @@ Host Stack ====== - Improve compiler support for CCRX and IAR -- Add timeout to osal_queue_receive() -- Add tud_task_ext(timeout, in_isr) as generic version of tud_task(). Same as tuh_task_ext(), tuh_task() -- Enable more warnings -Wnull-dereference -Wuninitialized -Wunused -Wredundant-decls -Wconversion +- Add timeout to ``osal_queue_receive()`` +- Add ``tud_task_ext(timeout, in_isr)`` as generic version of ``tud_task()``. Same as ``tuh_task_ext()``, ``tuh_task()`` +- Enable more warnings ``-Wnull-dereference -Wuninitialized -Wunused -Wredundant-decls -Wconversion`` - Add new examples - - host/bare_api to demonstrate generic (app-level) enumeration and endpoint transfer - - dual/host_hid_to_device_cdc to run both device and host stack concurrently, get HID report from host and print out to device CDC. This example only work with multiple-controller MCUs and rp2040 with the help of pio-usb as added controller. + - ``host/bare_api`` to demonstrate generic (app-level) enumeration and endpoint transfer + - ``dual/host_hid_to_device_cdc`` to run both device and host stack concurrently, get HID report from host and print out to device CDC. This example only work with multiple-controller MCUs and rp2040 with the help of pio-usb as added controller. Controller Driver (DCD & HCD) ----------------------------- - Enhance rhports management to better support dual roles - - CFG_TUD_ENABLED/CFG_TUH_ENABLED, CFG_TUD_MAX_SPEED/CFG_TUH_MAX_SPEED can be used to replace CFG_TUSB_RHPORT0_MODE/CFG_TUSB_RHPORT1_MODE - - tud_init(rphort), tuh_init(rhport) can be used to init stack on specified roothub port (controller) instead of tusb_init(void) -- Add dcd/hcd port specific defines `TUP_` (stand for tinyusb port-specific) + - ``CFG_TUD_ENABLED``/``CFG_TUH_ENABLED``, ``CFG_TUD_MAX_SPEED``/``CFG_TUH_MAX_SPEED`` can be used to replace ``CFG_TUSB_RHPORT0_MODE``/``CFG_TUSB_RHPORT1_MODE`` + - ``tud_init(rphort)``, ``tuh_init(rhport)`` can be used to init stack on specified roothub port (controller) instead of ``tusb_init(void)`` +- Add dcd/hcd port specific defines ``TUP_`` (stand for tinyusb port-specific) - [dwc2] - Update to support stm32 h72x, h73x with only 1 otg controller @@ -469,10 +469,10 @@ Device Stack - [Audio] Add support for feedback endpoint computation - - New API tud_audio_feedback_params_cb(), tud_audio_feedback_interval_isr(). + - New API ``tud_audio_feedback_params_cb()``, ``tud_audio_feedback_interval_isr()``. - Supported computation method are: frequency with fixed/float or power of 2. Feedback with fifo count is not yet supported. - - Fix nitfs (should be 3) in TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR - - Fix typo in audiod_rx_done_cb() + - Fix nitfs (should be 3) in ``TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR`` + - Fix typo in ``audiod_rx_done_cb()`` - [DFU] Fix coexistence with other interfaces BTH, RNDIS - [MSC] Fix inquiry response additional length field @@ -481,23 +481,23 @@ Device Stack Host Stack ---------- -- Add new API tuh_configure(rhport, cfg_id, cfg_param) for dynamnic port specific behavior configuration +- Add new API ``tuh_configure(rhport, cfg_id, cfg_param)`` for dynamnic port specific behavior configuration - [HID] Open OUT endpoint if available - [Hub] hub clear port and device interrupts - [USBH] Major improvement - - Rework usbh control transfer with complete callback. New API tuh_control_xfer() though still only carry 1 usbh (no queueing) at a time. - - Add generic endpoint transfer with tuh_edpt_open(), tuh_edpt_xfer(). Require `CFG_TUH_API_EDPT_XFER=1` + - Rework usbh control transfer with complete callback. New API ``tuh_control_xfer()`` though still only carry 1 usbh (no queueing) at a time. + - Add generic endpoint transfer with ``tuh_edpt_open()``, ``tuh_edpt_xfer()``. Require ``CFG_TUH_API_EDPT_XFER=1`` - Support app-level enumeration with new APIs - - tuh_descriptor_get(), tuh_descriptor_get_device(), tuh_descriptor_get_configuration(), tuh_descriptor_get_hid_report() - - tuh_descriptor_get_string(), tuh_descriptor_get_manufacturer_string(), tuh_descriptor_get_product_string(), tuh_descriptor_get_serial_string() - - Also add _sync() as sync/blocking version for above APIs + - ``tuh_descriptor_get()``, ``tuh_descriptor_get_device()``, ``tuh_descriptor_get_configuration()``, ``tuh_descriptor_get_hid_report()`` + - ``tuh_descriptor_get_string()``, ``tuh_descriptor_get_manufacturer_string()``, ``tuh_descriptor_get_product_string()``, ``tuh_descriptor_get_serial_string()`` + - Also add ``_sync()`` as sync/blocking version for above APIs 0.13.0 ====== -- [tu_fifo] Fix locked mutex when full, and return type in peek_n() +- [tu_fifo] Fix locked mutex when full, and return type in ``peek_n()`` Controller Driver (DCD & HCD) ----------------------------- @@ -526,7 +526,7 @@ Device Stack ------------ - [Audio] Support disabling feedback format correction (16.16 <-> 10.14 format) -- [MSC] Add tud_msc_request_sense_cb() callback, change most default sense error to medium not present (0x02, 0x3A, 0x00) +- [MSC] Add ``tud_msc_request_sense_cb()`` callback, change most default sense error to medium not present (0x02, 0x3A, 0x00) - [Video] Fix video_capture example fails enumeration when 8FPS Host Stack @@ -537,22 +537,22 @@ No notable changes 0.12.0 ====== -- add CFG_TUSB_OS_INC_PATH for os include path +- add ``CFG_TUSB_OS_INC_PATH`` for os include path Device Controller Driver (DCD) ------------------------------ - Getting device stack to pass USB Compliance Verification test (chapter9, HID, MSC). Ports are tested: nRF, SAMD 21/51, rp2040, stm32f4, Renesas RX, iMXRT, ESP32-S2/3, Kinetic KL25/32, DA146xx -- Added dcd_edpt_close_all() for switching configuration -- [Transdimension] Support dcd_edpt_xfer_fifo() with auto wrap over if fifo buffer is 4K aligned and size is multiple of 4K. +- Added ``dcd_edpt_close_all()`` for switching configuration +- [Transdimension] Support ``dcd_edpt_xfer_fifo()`` with auto wrap over if fifo buffer is 4K aligned and size is multiple of 4K. - [DA146xx] Improve vbus, reset, suspend, resume detection, and remote wakeup. Device Stack ------------ -- Add new network driver Network Control Model (CDC-NCM), update net_lwip_webserver to work with NCM (need re-configure example) -- Add new USB Video Class UVC 1.5 driver and video_capture example ((work in progress) +- Add new network driver Network Control Model (CDC-NCM), update ``net_lwip_webserver`` to work with NCM (need re-configure example) +- Add new USB Video Class UVC 1.5 driver and video_capture example (work in progress) - Fix potential buffer overflow for HID, bluetooth drivers Host Controller Driver (HCD) @@ -589,13 +589,13 @@ Synopsys ^^^^^^^^ - Fix Synopsys set address bug which could cause re-enumeration failed -- Fix dcd_synopsys driver integer overflow in HS mode (issue #968) +- Fix ``dcd_synopsys`` driver integer overflow in HS mode (issue #968) nRF5x ^^^^^ - Add nRF5x suspend, resume and remote wakeup -- Fix nRF5x race condition with TASKS_EP0RCVOUT +- Fix nRF5x race condition with ``TASKS_EP0RCVOUT`` RP2040 ^^^^^^ @@ -610,8 +610,8 @@ USBD ^^^^ - Better support big endian mcu -- Add tuh_inited() and tud_inited(), will separate tusb_init/inited() to tud/tuh init/inited -- Add dcd_attr.h for defining common controller attribute such as max endpoints +- Add ``tuh_inited()`` and ``tud_inited()``, will separate ``tusb_init/inited()`` to ``tud/tuh_init/inited()`` +- Add ``dcd_attr.h`` for defining common controller attribute such as max endpoints Bluetooth ^^^^^^^^^ @@ -621,8 +621,8 @@ Bluetooth DFU ^^^ -- Enhance DFU implementation to support multiple alternate interface and better support bwPollTimeout -- Rename CFG_TUD_DFU_MODE to simply CFG_TUD_DFU +- Enhance DFU implementation to support multiple alternate interface and better support ``bwPollTimeout`` +- Rename ``CFG_TUD_DFU_MODE`` to simply ``CFG_TUD_DFU`` HID ^^^ @@ -647,7 +647,7 @@ Vendor ^^^^^^ - Fix vendor fifo deadlock in certain case -- Add tud_vendor_n_read_flush +- Add ``tud_vendor_n_read_flush()`` Host Controller Driver (HCD) ---------------------------- @@ -664,7 +664,7 @@ Host Stack - Major update and rework most of host stack, still needs more improvement - Lots of improvement and update in parsing configuration and control - Rework and major update to HID driver. Will default to enable boot interface if available -- Separate CFG_TUH_DEVICE_MAX and CFG_TUH_HUB for better management and reduce SRAM usage +- Separate ``CFG_TUH_DEVICE_MAX`` and ``CFG_TUH_HUB`` for better management and reduce SRAM usage 0.10.1 (2021-06-03) =================== @@ -676,9 +676,9 @@ Host Controller Driver (HCD) - Fix rp2040 host driver: incorrect PID with low speed device with max packet size of 8 bytes - Improve hub driver -- Remove obsolete hcd_pipe_queue_xfer()/hcd_pipe_xfer() -- Use hcd_frame_number() instead of micro frame -- Fix OHCI endpoint address and xferred_bytes in xfer complete event +- Remove obsolete ``hcd_pipe_queue_xfer()``/``hcd_pipe_xfer()`` +- Use ``hcd_frame_number()`` instead of micro frame +- Fix OHCI endpoint address and ``xferred_bytes`` in xfer complete event 0.10.0 (2021-05-28) =================== @@ -697,7 +697,7 @@ Device Controller Driver (DCD) - Fix build with nRF5340 - Fix build with lpc15 and lpc54 - Fix build with lpc177x_8x -- STM32 Synopsys: greatly improve Isochronous transfer with edpt_xfer_fifo API +- STM32 Synopsys: greatly improve Isochronous transfer with ``edpt_xfer_fifo()`` API - Support LPC55 port1 highspeed - Add support for Espressif esp32s3 - nRF: fix race condition that could cause drop packet of Bulk OUT transfer @@ -705,14 +705,14 @@ Device Controller Driver (DCD) USB Device Driver (USBD) ------------------------ -- Add new (optional) endpoint ADPI usbd_edpt_xfer_fifo +- Add new (optional) endpoint ADPI ``usbd_edpt_xfer_fifo()`` Device Class Driver ------------------- CDC -- [Breaking] tud_cdc_peek(), tud_vendor_peek() no longer support random offset and dropped position parameter. +- [Breaking] ``tud_cdc_peek()``, ``tud_vendor_peek()`` no longer support random offset and dropped position parameter. DFU @@ -724,19 +724,19 @@ HID - Add more hid keys constant from 0x6B to 0xA4 - [Breaking] rename API - - HID_PROTOCOL_NONE/KEYBOARD/MOUST to HID_ITF_PROTOCOL_NONE/KEYBOARD/MOUSE - - tud_hid_boot_mode() to tud_hid_get_protocol() - - tud_hid_boot_mode_cb() to tud_hid_set_protocol_cb() + - ``HID_PROTOCOL_NONE/KEYBOARD/MOUSE`` to ``HID_ITF_PROTOCOL_NONE/KEYBOARD/MOUSE`` + - ``tud_hid_boot_mode()`` to ``tud_hid_get_protocol()`` + - ``tud_hid_boot_mode_cb()`` to ``tud_hid_set_protocol_cb()`` MIDI - Fix MIDI buffer overflow issue - [Breaking] rename API - - Rename tud_midi_read() to tud_midi_stream_read() - - Rename tud_midi_write() to tud_midi_stream_write() - - Rename tud_midi_receive() to tud_midi_packet_read() - - Rename tud_midi_send() to tud_midi_packet_write() + - Rename ``tud_midi_read()`` to ``tud_midi_stream_read()`` + - Rename ``tud_midi_write()`` to ``tud_midi_stream_write()`` + - Rename ``tud_midi_receive()`` to ``tud_midi_packet_read()`` + - Rename ``tud_midi_send()`` to ``tud_midi_packet_write()`` Host Controller Driver (HCD) ---------------------------- @@ -783,7 +783,7 @@ NXP Transdimention USB Device Driver (USBD) ^^^^^^^^^^^^^^^^^^^^^^^^ -- Fix issue with status zlp (tud_control_status) is returned by class driver with SET/CLEAR_FEATURE for endpoint. +- Fix issue with status zlp (``tud_control_status()``) is returned by class driver with SET/CLEAR_FEATURE for endpoint. - Correct endpoint size check for fullspeed bulk, can be 8, 16, 32, 64 - Ack SET_INTERFACE even if it is not implemented by class driver. @@ -792,34 +792,34 @@ Device Class Driver DFU Runtime -- rename dfu_rt to dfu_runtime for easy reading +- rename ``dfu_rt()`` to ``dfu_runtime()`` for easy reading CDC -- Add tud_cdc_send_break_cb() to support break request -- Improve CDC receive, minor behavior changes: when tud_cdc_rx_wanted_cb() is invoked wanted_char may not be the last byte in the fifo +- Add ``tud_cdc_send_break_cb()`` to support break request +- Improve CDC receive, minor behavior changes: when ``tud_cdc_rx_wanted_cb()`` is invoked wanted_char may not be the last byte in the fifo HID - [Breaking] Add itf argument to hid API to support multiple instances, follow API has signature changes - - tud_hid_descriptor_report_cb() - - tud_hid_get_report_cb() - - tud_hid_set_report_cb() - - tud_hid_boot_mode_cb() - - tud_hid_set_idle_cb() + - ``tud_hid_descriptor_report_cb()`` + - ``tud_hid_get_report_cb()`` + - ``tud_hid_set_report_cb()`` + - ``tud_hid_boot_mode_cb()`` + - ``tud_hid_set_idle_cb()`` -- Add report complete callback tud_hid_report_complete_cb() API +- Add report complete callback ``tud_hid_report_complete_cb()`` API - Add DPad/Hat support for HID Gamepad - - `TUD_HID_REPORT_DESC_GAMEPAD()` now support 16 buttons, 2 joysticks, 1 hat/dpad - - Add hid_gamepad_report_t along with `GAMEPAD_BUTTON_` and `GAMEPAD_HAT_` enum - - Add Gamepad to hid_composite / hid_composite_freertos example + - ``TUD_HID_REPORT_DESC_GAMEPAD()`` now support 16 buttons, 2 joysticks, 1 hat/dpad + - Add ``hid_gamepad_report_t`` along with ``GAMEPAD_BUTTON_`` and ``GAMEPAD_HAT_`` enum + - Add Gamepad to ``hid_composite`` / ``hid_composite_freertos`` example MIDI - Fix dropping MIDI sysex message when fifo is full -- Fix typo in tud_midi_write24(), make example less ambiguous for cable and channel +- Fix typo in ``tud_midi_write24()``, make example less ambiguous for cable and channel - Fix incorrect endpoint descriptor length, MIDI v1 use Audio v1 which has 9-byte endpoint descriptor (instead of 7) Host Stack @@ -828,14 +828,14 @@ Host Stack Host Controller Driver (HCD) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- Add rhport to hcd_init() +- Add rhport to ``hcd_init()`` - Improve EHCI/OHCI driver abstraction - Move echi/ohci files to portable/ - - Rename hcd_lpc18_43 to hcd_transdimension - - Sub hcd API with hcd_ehci_init(), hcd_ehci_register_addr() + - Rename ``hcd_lpc18_43`` to ``hcd_transdimension`` + - Sub hcd API with ``hcd_ehci_init()``, ``hcd_ehci_register_addr()`` -- Update NXP transdimention hcd_init() to reset controller to host mode +- Update NXP transdimension ``hcd_init()`` to reset controller to host mode - Ported hcd to rt10xx @@ -849,20 +849,20 @@ Host Class Driver MSC -- Rename tuh_msc_scsi_inquiry() to tuh_msc_inquiry() -- Rename tuh_msc_mounted_cb/tuh_msc_unmounted_cb to tuh_msc_mount_cb/tuh_msc_unmount_cb to match device stack naming -- Change tuh_msc_is_busy() to tuh_msc_ready() -- Add read10 and write10 function: tuh_msc_read10(), tuh_msc_write10() +- Rename ``tuh_msc_scsi_inquiry()`` to ``tuh_msc_inquiry()`` +- Rename ``tuh_msc_mounted_cb()``/``tuh_msc_unmounted_cb()`` to ``tuh_msc_mount_cb()``/``tuh_msc_unmount_cb()`` to match device stack naming +- Change ``tuh_msc_is_busy()`` to ``tuh_msc_ready()`` +- Add read10 and write10 function: ``tuh_msc_read10()``, ``tuh_msc_write10()`` - Read_Capacity is invoked as part of enumeration process -- Add tuh_msc_get_block_count(), tuh_msc_get_block_size() -- Add CFG_TUH_MSC_MAXLUN (default to 4) to hold lun capacities +- Add ``tuh_msc_get_block_count()``, ``tuh_msc_get_block_size()`` +- Add ``CFG_TUH_MSC_MAXLUN`` (default to 4) to hold lun capacities Others ------ - Add basic support for rt-thread OS - Change zero bitfield length to more explicit padding -- Build example now fetch required submodules on the fly while running `make` without prio submodule init for mcu drivers +- Build example now fetch required submodules on the fly while running ``make`` without prior submodule init for mcu drivers - Update pico-sdk to v1.1.0 **New Boards** @@ -880,7 +880,7 @@ Device Controller Driver - Added new device support for Raspberry Pi RP2040 - Added new device support for NXP Kinetis KL25ZXX -- Use dcd_event_bus_reset() with link speed to replace bus_signal +- Use ``dcd_event_bus_reset()`` with link speed to replace bus_signal - ESP32-S2: - Add bus suspend and wakeup support @@ -902,8 +902,8 @@ USB Device **USBD** - Rework usbd control transfer to have additional stage parameter for setup, data, status -- Fix tusb_init() return true instead of TUSB_ERROR_NONE -- Added new API tud_connected() that return true after device got out of bus reset and received the very first setup packet +- Fix ``tusb_init()`` return true instead of ``TUSB_ERROR_NONE`` +- Added new API ``tud_connected()`` that return true after device got out of bus reset and received the very first setup packet **Class Driver** @@ -911,22 +911,22 @@ USB Device - Allow to transmit data, even if the host does not support control line states i.e set DTR - HID - - change default CFG_TUD_HID_EP_BUFSIZE from 16 to 64 + - change default ``CFG_TUD_HID_EP_BUFSIZE`` from 16 to 64 - MIDI - Fix midi sysex sending bug - MSC - Invoke only scsi complete callback after status transaction is complete. - - Fix scsi_mode_sense6_t padding, which cause IAR compiler internal error. + - Fix ``scsi_mode_sense6_t`` padding, which cause IAR compiler internal error. - USBTMC - Change interrupt endpoint example size to 8 instead of 2 for better compatibility with mcu **Example** -- Support make from windows cmd.exe -- Add HID Consumer Control (media keys) to hid_composite & hid_composite_freertos examples +- Support make from windows ``cmd.exe`` +- Add HID Consumer Control (media keys) to ``hid_composite`` & ``hid_composite_freertos`` examples USB Host @@ -967,28 +967,28 @@ Device Controller Driver - Support multiple usb ports with rhport=1 is highspeed on selected MCUs e.g H743, F23. It is possible to have OTG_HS to run on Fullspeed PHY (e.g lacking external PHY) - Add ISO transfer, fix odd/even frame - Fix FIFO flush during stall - - Implement dcd_edpt_close() API + - Implement ``dcd_edpt_close()`` API - Support F105, F107 - Enhance STM32 fsdev - Improve dcd fifo allocation - Fix ISTR race condition - Support remap USB IRQ on supported MCUs - - Implement dcd_edpt_close() API + - Implement ``dcd_edpt_close()`` API - Enhance NUC 505: enhance set configure behavior - Enhance SAMD - Fix race condition with setup packet - - Add SAMD11 option `OPT_MCU_SAMD11` - - Add SAME5x option `OPT_MCU_SAME5X` + - Add SAMD11 option ``OPT_MCU_SAMD11`` + - Add SAME5x option ``OPT_MCU_SAME5X`` - Fix SAMG control data toggle and stall race condition - Enhance nRF - - Fix hanged when tud_task() is called within critical section (disabled interrupt) + - Fix hanged when ``tud_task()`` is called within critical section (disabled interrupt) - Fix disconnect bus event not submitted - - Implement ISO transfer and dcd_edpt_close() + - Implement ISO transfer and ``dcd_edpt_close()`` USB Device @@ -997,26 +997,26 @@ USB Device **USBD** - Add new class driver for **Bluetooth HCI** class driver with example can be found in [mynewt-tinyusb-example](https://github.com/hathach/mynewt-tinyusb-example) since it needs mynewt OS to run with. -- Fix USBD endpoint usage racing condition with `usbd_edpt_claim()/usbd_edpt_release()` -- Added `tud_task_event_ready()` and `osal_queue_empty()`. This API is needed to check before enter low power mode with WFI/WFE -- Rename USB IRQ Handler to `dcd_int_handler()`. Application must define IRQ handler in which it calls this API. -- Add `dcd_connect()` and `dcd_disconnect()` to enable/disable internal pullup on D+/D- on supported MCUs. -- Add `usbd_edpt_open()` -- Remove `dcd_set_config()` -- Add *OPT_OS_CUMSTOM* as hook for application to overwrite and/or add their own OS implementation +- Fix USBD endpoint usage racing condition with ``usbd_edpt_claim()``/``usbd_edpt_release()`` +- Added ``tud_task_event_ready()`` and ``osal_queue_empty()``. This API is needed to check before enter low power mode with WFI/WFE +- Rename USB IRQ Handler to ``dcd_int_handler()``. Application must define IRQ handler in which it calls this API. +- Add ``dcd_connect()`` and ``dcd_disconnect()`` to enable/disable internal pullup on D+/D- on supported MCUs. +- Add ``usbd_edpt_open()`` +- Remove ``dcd_set_config()`` +- Add ``OPT_OS_CUMSTOM`` as hook for application to overwrite and/or add their own OS implementation - Support SET_INTERFACE, GET_INTERFACE request -- Add Logging for debug with optional uart/rtt/swo printf retarget or `CFG_TUSB_DEBUG_PRINTF` hook +- Add Logging for debug with optional uart/rtt/swo printf retarget or ``CFG_TUSB_DEBUG_PRINTF`` hook - Add IAR compiler support -- Support multiple configuration descriptors. `TUD_CONFIG_DESCRIPTOR()` template has extra config_num as 1st argument -- Improve USB Highspeed support with actual link speed detection with `dcd_event_bus_reset()` +- Support multiple configuration descriptors. ``TUD_CONFIG_DESCRIPTOR()`` template has extra config_num as 1st argument +- Improve USB Highspeed support with actual link speed detection with ``dcd_event_bus_reset()`` - Enhance class driver management - - `usbd_driver_open()` add max length argument, and return length of interface (0 for not supported). Return value is used for finding appropriate driver - - Add application implemented class driver via `usbd_app_driver_get_cb()` + - ``usbd_driver_open()`` add max length argument, and return length of interface (0 for not supported). Return value is used for finding appropriate driver + - Add application implemented class driver via ``usbd_app_driver_get_cb()`` - IAD is handled to assign driver id -- Added `tud_descriptor_device_qualifier_cb()` callback -- Optimize `tu_fifo` bulk write/read transfer +- Added ``tud_descriptor_device_qualifier_cb()`` callback +- Optimize ``tu_fifo`` bulk write/read transfer - Forward non-std control request to class driver - Let application handle Microsoft OS 1.0 Descriptors (the 0xEE index string) - Fix OSAL FreeRTOS yield from ISR @@ -1028,8 +1028,8 @@ USB Device - CDC: - Send zero length packet for end of data when needed - - Add `tud_cdc_tx_complete_cb()` callback - - Change tud_cdc_n_write_flush() return number of bytes forced to transfer, and flush when writing enough data to fifo + - Add ``tud_cdc_tx_complete_cb()`` callback + - Change ``tud_cdc_n_write_flush()`` return number of bytes forced to transfer, and flush when writing enough data to fifo - MIDI: - Add packet interface @@ -1039,10 +1039,10 @@ USB Device - DFU Runtime: fix response to SET_INTERFACE and DFU_GETSTATUS request - Rename some configure macro to make it clear that those are used directly for endpoint transfer - - CFG_TUD_HID_BUFSIZE to CFG_TUD_HID_EP_BUFSIZE - - CFG_TUD_CDC_EPSIZE to CFG_TUD_CDC_EP_BUFSIZE - - CFG_TUD_MSC_BUFSIZE to CFG_TUD_MSC_EP_BUFSIZE - - CFG_TUD_MIDI_EPSIZE to CFG_TUD_MIDI_EP_BUFSIZE + - ``CFG_TUD_HID_BUFSIZE`` to ``CFG_TUD_HID_EP_BUFSIZE`` + - ``CFG_TUD_CDC_EPSIZE`` to ``CFG_TUD_CDC_EP_BUFSIZE`` + - ``CFG_TUD_MSC_BUFSIZE`` to ``CFG_TUD_MSC_EP_BUFSIZE`` + - ``CFG_TUD_MIDI_EPSIZE`` to ``CFG_TUD_MIDI_EP_BUFSIZE`` - HID: - Fix gamepad template descriptor @@ -1061,15 +1061,15 @@ USB Host Examples -------- -- Add new hid_composite_freertos -- Add new dynamic_configuration to demonstrate how to switch configuration descriptors -- Add new hid_multiple_interface +- Add new ``hid_composite_freertos`` +- Add new ``dynamic_configuration`` to demonstrate how to switch configuration descriptors +- Add new ``hid_multiple_interface`` -- Enhance `net_lwip_webserver` example +- Enhance ``net_lwip_webserver`` example - Add multiple configuration: RNDIS for Windows, CDC-ECM for macOS (Linux will work with both) - - Update lwip to STABLE-2_1_2_RELEASE for net_lwip_webserver + - Update lwip to STABLE-2_1_2_RELEASE for ``net_lwip_webserver`` -- Added new Audio example: audio_test uac2_headsest +- Added new Audio example: ``audio_test`` ``uac2_headsest`` New Boards ---------- @@ -1110,37 +1110,37 @@ Added - Added multiple instances support for CDC and MIDI - Added a handful of unit test with Ceedling. - Added LOG support for debugging with CFG_TUSB_DEBUG -- Added `tud_descriptor_bos_cb()` for BOS descriptor (required for USB 2.1) -- Added `dcd_edpt0_status_complete()` as optional API for DCD +- Added ``tud_descriptor_bos_cb()`` for BOS descriptor (required for USB 2.1) +- Added ``dcd_edpt0_status_complete()`` as optional API for DCD **Examples** Following examples are added: -- board_test -- cdc_dual_ports -- dfu_rt -- hid_composite -- net_lwip_webserver -- usbtmc -- webusb_serial +- ``board_test`` +- ``cdc_dual_ports`` +- ``dfu_rt`` +- ``hid_composite`` +- ``net_lwip_webserver`` +- ``usbtmc`` +- ``webusb_serial`` Changed ------- -- Changed `tud_descriptor_string_cb()` to have additional Language ID argument -- Merged hal_nrf5x.c into dcd_nrf5x.c -- Merged dcd_samd21.c and dcd_samd51.c into dcd_samd.c -- Generalized dcd_stm32f4.c to dcd_synopsys.c -- Changed cdc_msc_hid to cdc_msc (drop hid) due to limited endpoints number of some MCUs +- Changed ``tud_descriptor_string_cb()`` to have additional Language ID argument +- Merged ``hal_nrf5x.c`` into ``dcd_nrf5x.c`` +- Merged ``dcd_samd21.c`` and ``dcd_samd51.c`` into ``dcd_samd.c`` +- Generalized ``dcd_stm32f4.c`` to ``dcd_synopsys.c`` +- Changed ``cdc_msc_hid`` to ``cdc_msc`` (drop hid) due to limited endpoints number of some MCUs - Improved DCD SAMD stability, fix missing setup packet occasionally -- Improved usbd/usbd_control with proper handling of zero-length packet (ZLP) +- Improved ``usbd/usbd_control`` with proper handling of zero-length packet (ZLP) - Improved STM32 DCD FSDev - Improved STM32 DCD Synopsys - Migrated CI from Travis to Github Action - Updated nrfx submodule to 2.1.0 - Fixed mynewt osal queue definition -- Fixed cdc_msc_freertos example build for all MCUs +- Fixed ``cdc_msc_freertos`` example build for all MCUs 0.5.0 (2019-06) diff --git a/docs/reference/getting_started.rst b/docs/reference/getting_started.rst index 963420f7b..37745d6a1 100644 --- a/docs/reference/getting_started.rst +++ b/docs/reference/getting_started.rst @@ -7,17 +7,17 @@ Add TinyUSB to your project It is relatively simple to incorporate tinyusb to your project -* Copy or ``git submodule`` this repo into your project in a subfolder. Let's say it is *your_project/tinyusb* -* Add all the .c in the ``tinyusb/src`` folder to your project -* Add *your_project/tinyusb/src* to your include path. Also make sure your current include path also contains the configuration file tusb_config.h. -* Make sure all required macros are all defined properly in tusb_config.h (configure file in demo application is sufficient, but you need to add a few more such as ``CFG_TUSB_MCU``, ``CFG_TUSB_OS`` since they are passed by IDE/compiler to maintain a unique configure for all boards). +* Copy or ``git submodule`` this repo into your project in a subfolder. Let's say it is ``your_project/tinyusb`` +* Add all the ``.c`` in the ``tinyusb/src`` folder to your project +* Add ``your_project/tinyusb/src`` to your include path. Also make sure your current include path also contains the configuration file ``tusb_config.h``. +* Make sure all required macros are all defined properly in ``tusb_config.h`` (configure file in demo application is sufficient, but you need to add a few more such as ``CFG_TUSB_MCU``, ``CFG_TUSB_OS`` since they are passed by IDE/compiler to maintain a unique configure for all boards). * If you use the device stack, make sure you have created/modified usb descriptors for your own need. Ultimately you need to implement all **tud descriptor** callbacks for the stack to work. -* Add tusb_init(rhport, role) call to your reset initialization code. +* Add ``tusb_init(rhport, role)`` call to your reset initialization code. * Call ``tusb_int_handler(rhport, in_isr)`` in your USB IRQ Handler * Implement all enabled classes's callbacks. -* If you don't use any RTOSes at all, you need to continuously and/or periodically call tud_task()/tuh_task() function. All of the callbacks and functionality are handled and invoked within the call of that task runner. +* If you don't use any RTOSes at all, you need to continuously and/or periodically call ``tud_task()``/``tuh_task()`` function. All of the callbacks and functionality are handled and invoked within the call of that task runner. -.. code-block:: +.. code-block:: c int main(void) { tusb_rhport_init_t dev_init = { @@ -50,9 +50,9 @@ It is relatively simple to incorporate tinyusb to your project Examples -------- -For your convenience, TinyUSB contains a handful of examples for both host and device with/without RTOS to quickly test the functionality as well as demonstrate how API() should be used. Most examples will work on most of `the supported boards `_. Firstly we need to ``git clone`` if not already +For your convenience, TinyUSB contains a handful of examples for both host and device with/without RTOS to quickly test the functionality as well as demonstrate how API should be used. Most examples will work on most of `the supported boards `_. Firstly we need to ``git clone`` if not already -.. code-block:: +.. code-block:: bash $ git clone https://github.com/hathach/tinyusb tinyusb $ cd tinyusb @@ -62,17 +62,17 @@ Some ports will also require a port-specific SDK (e.g. RP2040) or binary (e.g. S Dependencies ^^^^^^^^^^^^ -The hardware code is located in ``hw/bsp`` folder, and is organized by family/boards. e.g raspberry_pi_pico is located in ``hw/bsp/rp2040/boards/raspberry_pi_pico`` where FAMILY=rp2040 and BOARD=raspberry_pi_pico. Before building, we firstly need to download dependencies such as: MCU low-level peripheral driver and external libraries e.g FreeRTOS (required by some examples). We can do that by either ways: +The hardware code is located in ``hw/bsp`` folder, and is organized by family/boards. e.g raspberry_pi_pico is located in ``hw/bsp/rp2040/boards/raspberry_pi_pico`` where ``FAMILY=rp2040`` and ``BOARD=raspberry_pi_pico``. Before building, we firstly need to download dependencies such as: MCU low-level peripheral driver and external libraries e.g FreeRTOS (required by some examples). We can do that by either ways: 1. Run ``tools/get_deps.py {FAMILY}`` script to download all dependencies for a family as follow. Note: For TinyUSB developer to download all dependencies, use FAMILY=all. -.. code-block:: +.. code-block:: bash $ python tools/get_deps.py rp2040 2. Or run the ``get-deps`` target in one of the example folder as follow. -.. code-block:: +.. code-block:: bash $ cd examples/device/cdc_msc $ make BOARD=raspberry_pi_pico get-deps @@ -84,19 +84,19 @@ Build To build example, first change directory to an example folder. -.. code-block:: +.. code-block:: bash $ cd examples/device/cdc_msc Then compile with ``make BOARD={board_name} all`` , for example -.. code-block:: +.. code-block:: bash $ make BOARD=raspberry_pi_pico all Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``99-tinyusb.rules`` and reload your udev is good to go -.. code-block:: +.. code-block:: bash $ cp examples/device/99-tinyusb.rules /etc/udev/rules.d/ $ sudo udevadm control --reload-rules && sudo udevadm trigger @@ -106,7 +106,7 @@ RootHub Port Selection If a board has several ports, one port is chosen by default in the individual board.mk file. Use option ``PORT=x`` To choose another port. For example to select the HS port of a STM32F746Disco board, use: -.. code-block:: +.. code-block:: bash $ make BOARD=stm32f746disco PORT=1 all @@ -115,16 +115,16 @@ Port Speed A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option ``SPEED=full/high`` e.g To force F723 operate at full instead of default high speed -.. code-block:: +.. code-block:: bash $ make BOARD=stm32f746disco SPEED=full all Size Analysis ~~~~~~~~~~~~~ -First install `linkermap tool `_ then ``linkermap`` target can be used to analyze code size. You may want to compile with ``NO_LTO=1`` since -flto merges code across .o files and make it difficult to analyze. +First install `linkermap tool `_ then ``linkermap`` target can be used to analyze code size. You may want to compile with ``NO_LTO=1`` since ``-flto`` merges code across ``.o`` files and make it difficult to analyze. -.. code-block:: +.. code-block:: bash $ make BOARD=feather_nrf52840_express NO_LTO=1 all linkermap @@ -133,16 +133,16 @@ Debug To compile for debugging add ``DEBUG=1``\ , for example -.. code-block:: +.. code-block:: bash $ make BOARD=feather_nrf52840_express DEBUG=1 all Log ~~~ -Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional ``LOG=``. LOG=1 will only print out error message, LOG=2 print more information with on-going events. LOG=3 or higher is not used yet. +Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional ``LOG=``. ``LOG=1`` will only print out error message, ``LOG=2`` print more information with on-going events. ``LOG=3`` or higher is not used yet. -.. code-block:: +.. code-block:: bash $ make BOARD=feather_nrf52840_express LOG=2 all @@ -164,7 +164,7 @@ By default log message is printed via on-board UART which is slow and take lots * Pros: should be compatible with more debugger that support SWO. * Software viewer should be provided along with your debugger driver. -.. code-block:: +.. code-block:: bash $ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all $ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all @@ -174,20 +174,20 @@ Flash ``flash`` target will use the default on-board debugger (jlink/cmsisdap/stlink/dfu) to flash the binary, please install those support software in advance. Some board use bootloader/DFU via serial which is required to pass to make command -.. code-block:: +.. code-block:: bash $ make BOARD=feather_nrf52840_express flash $ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash Since jlink can be used with most of the boards, there is also ``flash-jlink`` target for your convenience. -.. code-block:: +.. code-block:: bash $ make BOARD=feather_nrf52840_express flash-jlink Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with ``uf2`` target -.. code-block:: +.. code-block:: bash $ make BOARD=feather_nrf52840_express all uf2 @@ -199,23 +199,23 @@ Use project connection IAR Project Connection files are provided to import TinyUSB stack into your project. -* A buldable project of your MCU need to be created in advance. +* A buildable project of your MCU need to be created in advance. * Take example of STM32F0: - - You need `stm32l0xx.h`, `startup_stm32f0xx.s`, `system_stm32f0xx.c`. + - You need ``stm32l0xx.h``, ``startup_stm32f0xx.s``, ``system_stm32f0xx.c``. - - `STM32L0xx_HAL_Driver` is only needed to run examples, TinyUSB stack itself doesn't rely on MCU's SDKs. + - ``STM32L0xx_HAL_Driver`` is only needed to run examples, TinyUSB stack itself doesn't rely on MCU's SDKs. -* Open ``Tools -> Configure Custom Argument Variables`` (Switch to `Global` tab if you want to do it for all your projects) - Click `New Group ...`, name it to `TUSB`, Click `Add Variable ...`, name it to `TUSB_DIR`, change it's value to the path of your TinyUSB stack, - for example `C:\\tinyusb` +* Open ``Tools -> Configure Custom Argument Variables`` (Switch to ``Global`` tab if you want to do it for all your projects) + Click ``New Group ...``, name it to ``TUSB``, Click ``Add Variable ...``, name it to ``TUSB_DIR``, change it's value to the path of your TinyUSB stack, + for example ``C:\\tinyusb`` Import stack only ~~~~~~~~~~~~~~~~~ -1. Open ``Project -> Add project Connection ...``, click `OK`, choose `tinyusb\\tools\\iar_template.ipcf`. +1. Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\tools\\iar_template.ipcf``. Run examples ~~~~~~~~~~~~ @@ -224,11 +224,11 @@ Run examples .. code-block:: - cd C:\tinyusb\tools - python iar_gen.py + > cd C:\tinyusb\tools + > python iar_gen.py -2. Open `Project -> Add project Connection ...`, click `OK`, choose `tinyusb\\examples\\(.ipcf of example)`. - For example `C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf` +2. Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\examples\\(.ipcf of example)``. + For example ``C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf`` Native CMake support (9.50.1+) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -239,5 +239,5 @@ Following these steps: 1. Add IAR compiler binary path to system ``PATH`` environment variable, such as ``C:\Program Files\IAR Systems\Embedded Workbench 9.2\arm\bin``. 2. Create new project in IAR, in Tool chain dropdown menu, choose CMake for Arm then Import ``CMakeLists.txt`` from chosen example directory. -3. Set up board option in ``Option - CMake/CMSIS-TOOLBOX - CMake``, for example :code:`-DBOARD=stm32f439nucleo -DTOOLCHAIN=iar`, **Uncheck 'Override tools in env'**. +3. Set up board option in ``Option - CMake/CMSIS-TOOLBOX - CMake``, for example ``-DBOARD=stm32f439nucleo -DTOOLCHAIN=iar``, **Uncheck 'Override tools in env'**. 4. (For debug only) Choose correct CPU model in ``Option - General Options - Target``, to profit register and memory view. From b80800f18205ae23d571438d55e078a1dcc295e8 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Thu, 13 Mar 2025 10:04:56 -0700 Subject: [PATCH 058/382] Only clear stream_read & stream_write if they are defined --- src/class/midi/midi_host.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 03144eb45..4d824e04c 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -153,9 +153,10 @@ void midih_close(uint8_t daddr) { p_midi->tx_cable_count = 0; p_midi->daddr = 0; p_midi->mounted = false; +#if CFG_TUH_MIDI_STREAM_API tu_memclr(&p_midi->stream_read, sizeof(p_midi->stream_read)); tu_memclr(&p_midi->stream_write, sizeof(p_midi->stream_write)); - +#endif tu_edpt_stream_close(&p_midi->ep_stream.rx); tu_edpt_stream_close(&p_midi->ep_stream.tx); } From ca750313b26254c3fbc66152b5e0ed9dfe415630 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 15 Mar 2025 21:15:52 +0100 Subject: [PATCH 059/382] Update gitignore. Signed-off-by: HiFiPhile --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index f981110b2..5638a09db 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,14 @@ latex *.jlink *.emSession *.ninja* +*.eww +*.ewp +*.ewt +*.ewd +*.hex +cmake_install.cmake +CMakeCache.txt +settings/ .settings/ .vscode/ .gdb_history From de45e4b01a55182f494577a8bf8b46ad51d6eb9f Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 15 Mar 2025 23:49:11 +0100 Subject: [PATCH 060/382] Add ctrl buffer alignment. Signed-off-by: HiFiPhile --- src/class/audio/audio_device.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 388168424..7a6fd453f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -208,15 +208,15 @@ tu_static CFG_TUD_MEM_SECTION struct { #endif// CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // Control buffers -tu_static uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; - -#if CFG_TUD_AUDIO > 1 -tu_static uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; -#endif - -#if CFG_TUD_AUDIO > 2 -tu_static uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; -#endif +tu_static CFG_TUD_MEM_SECTION struct { + TUD_EPBUF_DEF(buf1, CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ); + #if CFG_TUD_AUDIO > 1 + TUD_EPBUF_DEF(buf2, CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ); + #endif + #if CFG_TUD_AUDIO > 2 + TUD_EPBUF_DEF(buf3, CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ); + #endif +} ctrl_buf; // Active alternate setting of interfaces tu_static uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; @@ -1223,18 +1223,18 @@ void audiod_init(void) { // Initialize control buffers switch (i) { case 0: - audio->ctrl_buf = ctrl_buf_1; + audio->ctrl_buf = ctrl_buf.buf1; audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ; break; #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0 case 1: - audio->ctrl_buf = ctrl_buf_2; + audio->ctrl_buf = ctrl_buf.buf2; audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ; break; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0 case 2: - audio->ctrl_buf = ctrl_buf_3; + audio->ctrl_buf = ctrl_buf.buf3; audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ; break; #endif From 585bcbfcdd5e24e25dd8d42b51446824b8143602 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 16 Mar 2025 00:07:15 +0100 Subject: [PATCH 061/382] Fix 2 IAR warnings. Signed-off-by: HiFiPhile --- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 7d5cfb5b0..7c637ce0c 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -297,7 +297,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dcd_reg->EPLISTSTART = (uint32_t) _dcd.ep; dcd_reg->DATABUFSTART = tu_align((uint32_t) &_dcd, TU_BIT(22)); // 22-bit alignment - dcd_reg->INTSTAT |= dcd_reg->INTSTAT; // clear all pending interrupt + dcd_reg->INTSTAT = dcd_reg->INTSTAT; // clear all pending interrupt dcd_reg->INTEN = INT_DEVICE_STATUS_MASK; dcd_reg->DEVCMDSTAT |= DEVCMDSTAT_DEVICE_ENABLE_MASK | DEVCMDSTAT_DEVICE_CONNECT_MASK | DEVCMDSTAT_RESET_CHANGE_MASK | DEVCMDSTAT_CONNECT_CHANGE_MASK | DEVCMDSTAT_SUSPEND_CHANGE_MASK; @@ -563,7 +563,8 @@ void dcd_int_handler(uint8_t rhport) uint32_t const cmd_stat = dcd_reg->DEVCMDSTAT; - uint32_t int_status = dcd_reg->INTSTAT & dcd_reg->INTEN; + uint32_t int_status = dcd_reg->INTSTAT; + int_status &= dcd_reg->INTEN; dcd_reg->INTSTAT = int_status; // Acknowledge handled interrupt if (int_status == 0) return; From c61dfc7c7a4744458b77caa4043af8b05a65fadc Mon Sep 17 00:00:00 2001 From: verylowfreq <60875431+verylowfreq@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:04:00 +0900 Subject: [PATCH 062/382] Add ch32v20x usbfs hcd initial support. --- hw/bsp/ch32v20x/family.c | 3 + hw/bsp/ch32v20x/family.mk | 3 + src/portable/wch/hcd_ch32_usbfs.c | 618 ++++++++++++++++++++++++++++++ 3 files changed, 624 insertions(+) create mode 100644 src/portable/wch/hcd_ch32_usbfs.c diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index 5f52d9447..8a9ee6819 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -32,6 +32,9 @@ void USBHD_IRQHandler(void) { #if CFG_TUD_WCH_USBIP_USBFS tud_int_handler(0); #endif + #if CFG_TUH_WCH_USBIP_USBFS + tuh_int_handler(0); + #endif } __attribute__((interrupt)) __attribute__((used)) diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk index 08761dc0d..16fc537ac 100644 --- a/hw/bsp/ch32v20x/family.mk +++ b/hw/bsp/ch32v20x/family.mk @@ -30,6 +30,8 @@ CFLAGS += -Wno-error=strict-prototypes ifeq ($(PORT),0) $(info "Using FSDEV driver") CFLAGS += -DCFG_TUD_WCH_USBIP_FSDEV=1 + $(info "Using USBFS Host driver") + CFLAGS += -DCFG_TUH_WCH_USBIP_USBFS=1 else $(info "Using USBFS driver") CFLAGS += -DCFG_TUD_WCH_USBIP_USBFS=1 @@ -43,6 +45,7 @@ LD_FILE = $(FAMILY_PATH)/linker/${CH32_FAMILY}.ld SRC_C += \ src/portable/wch/dcd_ch32_usbfs.c \ + src/portable/wch/hcd_ch32_usbfs.c \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ $(SDK_SRC_DIR)/Core/core_riscv.c \ $(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \ diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c new file mode 100644 index 000000000..534edb22b --- /dev/null +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -0,0 +1,618 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2024 Mitsumine Suzu (verylowfreq) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if CFG_TUH_ENABLED && defined(TUP_USBIP_WCH_USBFS) && CFG_TUH_WCH_USBIP_USBFS + +#include "host/hcd.h" +#include "host/usbh.h" +#include "host/usbh_pvt.h" + +#include "bsp/board_api.h" + +#include "ch32v20x.h" +#include "ch32v20x_usb.h" + + +#define USBFS_RX_BUF_LEN 64 +#define USBFS_TX_BUF_LEN 64 +__attribute__((aligned(4))) static uint8_t USBFS_RX_Buf[USBFS_RX_BUF_LEN]; +__attribute__((aligned(4))) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN]; + +#define USB_XFER_TIMEOUT_MILLIS 500 + +#define PANIC(...) do { printf("\r\nPANIC: " __VA_ARGS__); while (true) { } } while (false) + +#define LOG_CH32_USBFSH(...) TU_LOG3(__VA_ARGS__) + +// Busywait for delay microseconds/nanoseconds +// static void loopdelay(uint32_t count) +// { +// volatile uint32_t c = count / 3; +// // while (c-- != 0); +// asm volatile( +// "1: \n" // loop label +// " addi %0, %0, -1 \n" // c-- +// " bne %0, zero, 1b \n" // if (c != 0) goto loop +// : "+r"(c) // c is input/output operand +// ); +// } + + +// Endpoint status +typedef struct usb_edpt +{ + // Is this a valid struct + bool configured; + + uint8_t dev_addr; + uint8_t ep_addr; + uint16_t max_packet_size; + + // Data toggle (0 or not 0) for DATA0/1 + uint8_t data_toggle; + + // Xfer started time in millis for timeout + uint32_t current_xfer_packet_start_millis; + uint8_t* current_xfer_buffer; + uint16_t current_xfer_bufferlen; + uint16_t current_xfer_xferred_len; + +} usb_edpt_t; + + +static usb_edpt_t usb_edpt_list[8] = { }; + + +static usb_edpt_t* get_edpt_record(uint8_t dev_addr, uint8_t ep_addr) +{ + for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) + { + usb_edpt_t* cur = &usb_edpt_list[i]; + if (cur->configured && cur->dev_addr == dev_addr && cur->ep_addr == ep_addr) + { + return cur; + } + } + return NULL; +} + +static usb_edpt_t* get_empty_record_slot(void) +{ + for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) + { + if (!usb_edpt_list[i].configured) + { + return &usb_edpt_list[i]; + } + } + return NULL; +} + +static usb_edpt_t* add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size) +{ + usb_edpt_t* slot = get_empty_record_slot(); + TU_ASSERT(slot != NULL, NULL); + + slot->dev_addr = dev_addr; + slot->ep_addr = ep_addr; + slot->max_packet_size = max_packet_size; + slot->data_toggle = 0; + slot->current_xfer_packet_start_millis = 0; + slot->current_xfer_buffer = NULL; + slot->current_xfer_bufferlen = 0; + slot->current_xfer_xferred_len = 0; + + slot->configured = true; + + return slot; +} + +static usb_edpt_t* get_or_add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size) +{ + usb_edpt_t* ret = get_edpt_record(dev_addr, ep_addr); + if (ret != NULL) + { + return ret; + } + else + { + return add_edpt_record(dev_addr, ep_addr, max_packet_size); + } +} + + +static void remove_edpt_record_for_device(uint8_t dev_addr) +{ + for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) + { + if (usb_edpt_list[i].configured && usb_edpt_list[i].dev_addr == dev_addr) + { + usb_edpt_list[i].configured = false; + } + } +} + + +/** Enable or disable USBFS Host function */ +static void hardware_init_host(bool enabled) +{ + // Reset USBOTG module + USBOTG_H_FS->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL; + + osal_task_delay(1); + USBOTG_H_FS->BASE_CTRL = 0; + + if (!enabled) + { + // Disable all feature + USBOTG_H_FS->BASE_CTRL = 0; + } + else + { + // Enable USB Host features + NVIC_DisableIRQ(USBFS_IRQn); + USBOTG_H_FS->BASE_CTRL = USBFS_UC_HOST_MODE | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN; + USBOTG_H_FS->HOST_EP_MOD = USBFS_UH_EP_TX_EN | USBFS_UH_EP_RX_EN; + USBOTG_H_FS->HOST_RX_DMA = (uint32_t)USBFS_RX_Buf; + USBOTG_H_FS->HOST_TX_DMA = (uint32_t)USBFS_TX_Buf; + USBOTG_H_FS->INT_EN = USBFS_UIE_TRANSFER | USBFS_UIE_DETECT; + } +} + +static bool hardware_start_xfer(uint8_t pid, uint8_t ep_addr, uint8_t data_toggle) +{ + LOG_CH32_USBFSH("hardware_start_xfer(pid=%s(0x%02x), ep_addr=0x%02x, toggle=%d)\r\n", + pid == USB_PID_IN ? "IN" : pid == USB_PID_OUT ? "OUT" : pid == USB_PID_SETUP ? "SETUP" : "(other)", + pid, ep_addr, data_toggle); + + if (pid == USB_PID_IN) + { // FIXME: long delay needed (at release build) about 30msec + // loopdelay(SystemCoreClock / 1000 * 30); + } + + uint8_t pid_edpt = (pid << 4) | (tu_edpt_number(ep_addr) & 0x0f); + USBOTG_H_FS->HOST_TX_CTRL = (data_toggle != 0) ? USBFS_UH_T_TOG : 0; + USBOTG_H_FS->HOST_RX_CTRL = (data_toggle != 0) ? USBFS_UH_R_TOG : 0; + USBOTG_H_FS->HOST_EP_PID = pid_edpt; + USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; + return true; +} + + +/** Set device address to communicate */ +static void update_device_address(uint8_t dev_addr) +{ + // Keep the bit of GP_BIT. Other 7bits are actual device address. + USBOTG_H_FS->DEV_ADDR = (USBOTG_H_FS->DEV_ADDR & USBFS_UDA_GP_BIT) | (dev_addr & USBFS_USB_ADDR_MASK); +} + +/** Set port speed */ +static void update_port_speed(tusb_speed_t speed) +{ + LOG_CH32_USBFSH("update_port_speed(%s)\r\n", speed == TUSB_SPEED_FULL ? "Full" : speed == TUSB_SPEED_LOW ? "Low" : "(invalid)"); + switch (speed) { + case TUSB_SPEED_LOW: + USBOTG_H_FS->BASE_CTRL |= USBFS_UC_LOW_SPEED; + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_LOW_SPEED; + USBOTG_H_FS->HOST_SETUP |= USBFS_UH_PRE_PID_EN; + return; + case TUSB_SPEED_FULL: + USBOTG_H_FS->BASE_CTRL &= ~USBFS_UC_LOW_SPEED; + USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED; + USBOTG_H_FS->HOST_SETUP &= ~USBFS_UH_PRE_PID_EN; + return; + default: + PANIC("update_port_speed(%d)\r\n", speed); + } +} + +static bool hardware_device_attached(void) +{ + return USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH; +} + + +//--------------------------------------------------------------------+ +// HCD API +//--------------------------------------------------------------------+ +bool hcd_init(uint8_t rhport) +{ + (void)rhport; + hardware_init_host(true); + + return true; +} + +bool hcd_deinit(uint8_t rhport) +{ + (void)rhport; + hardware_init_host(false); + + return true; +} + +void hcd_port_reset(uint8_t rhport) +{ + (void)rhport; + LOG_CH32_USBFSH("hcd_port_reset()\r\n"); + NVIC_DisableIRQ(USBFS_IRQn); + update_device_address( 0x00 ); + + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_BUS_RESET; + osal_task_delay(15); + USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_BUS_RESET; + osal_task_delay(2); + + if ((USBOTG_H_FS->HOST_CTRL & USBFS_UH_PORT_EN) == 0) + { + if (hcd_port_speed_get(0) == TUSB_SPEED_LOW) + { + update_port_speed(TUSB_SPEED_LOW); + } + } + + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; + USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; + + return; +} + +void hcd_port_reset_end(uint8_t rhport) +{ + (void)rhport; + LOG_CH32_USBFSH("hcd_port_reset_end()\r\n"); + // Suppress the attached event + USBOTG_H_FS->INT_FG |= USBFS_UIF_DETECT; + NVIC_EnableIRQ(USBFS_IRQn); + + return; +} + +bool hcd_port_connect_status(uint8_t rhport) +{ + (void)rhport; + + return hardware_device_attached(); +} + +tusb_speed_t hcd_port_speed_get(uint8_t rhport) +{ + (void)rhport; + if (USBOTG_H_FS->MIS_ST & USBFS_UMS_DM_LEVEL) + { + return TUSB_SPEED_LOW; + } + else + { + return TUSB_SPEED_FULL; + } +} + +// Close all opened endpoint belong to this device +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) +{ + (void)rhport; + LOG_CH32_USBFSH("hcd_device_close(%d, 0x%02x)\r\n", rhport, dev_addr); + remove_edpt_record_for_device(dev_addr); + + return; +} + +uint32_t hcd_frame_number(uint8_t rhport) +{ + (void)rhport; + + return board_millis(); +} + +void hcd_int_enable(uint8_t rhport) +{ + (void)rhport; + NVIC_EnableIRQ(USBFS_IRQn); + + return; +} + +void hcd_int_disable(uint8_t rhport) +{ + (void)rhport; + NVIC_DisableIRQ(USBFS_IRQn); + + return; +} + +void hcd_int_handler(uint8_t rhport, bool in_isr) +{ + (void)rhport; + (void)in_isr; + + if (USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT) + { + // Clear the flag + USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT; + // Read the detection state + bool attached = hardware_device_attached(); + LOG_CH32_USBFSH("hcd_int_handler() attached = %d\r\n", attached ? 1 : 0); + if (attached) + { + hcd_event_device_attach(rhport, true); + } + else + { + hcd_event_device_remove(rhport, true); + } + return; + } + + if (USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER) + { + // Copy PID and Endpoint + uint8_t pid_edpt = USBOTG_H_FS->HOST_EP_PID; + uint8_t status = USBOTG_H_FS->INT_ST; + // Clear register to stop transfer + USBOTG_H_FS->HOST_EP_PID = 0; + // Clear the flag + USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; + + LOG_CH32_USBFSH("hcd_int_handler() pid_edpt=0x%02x\r\n", pid_edpt); + + uint8_t request_pid = pid_edpt >> 4; + uint8_t response_pid = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK; + uint8_t dev_addr = USBOTG_H_FS->DEV_ADDR; + uint8_t ep_addr = pid_edpt & 0x0f; + if (request_pid == USB_PID_IN) + { + ep_addr |= 0x80; + } + + usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr); + if (edpt_info == NULL) + { + PANIC("\r\nget_edpt_record() returned NULL in USBHD_IRQHandler\r\n"); + } + + if (status & USBFS_UIS_TOG_OK) + { + edpt_info->data_toggle ^= 0x01; + + switch (request_pid) + { + case USB_PID_SETUP: + case USB_PID_OUT: + { + uint16_t xferred_len = edpt_info->current_xfer_bufferlen; + hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); + return; + } + case USB_PID_IN: + { + uint16_t received_len = USBOTG_H_FS->RX_LEN; + edpt_info->current_xfer_xferred_len += received_len; + uint16_t xferred_len = edpt_info->current_xfer_xferred_len; + LOG_CH32_USBFSH("Read %d bytes\r\n", received_len); + // if (received_len > 0 && (edpt_info->current_xfer_buffer == NULL || edpt_info->current_xfer_bufferlen == 0)) { + // PANIC("Data received but buffer not set\r\n"); + // } + memcpy(edpt_info->current_xfer_buffer, USBFS_RX_Buf, received_len); + edpt_info->current_xfer_buffer += received_len; + if ((received_len < edpt_info->max_packet_size) || (xferred_len == edpt_info->current_xfer_bufferlen)) + { + // USB device sent all data. + LOG_CH32_USBFSH("USB_PID_IN completed\r\n"); + hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); + return; + } + else + { + // USB device may send more data. + LOG_CH32_USBFSH("Read more data\r\n"); + hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); + return; + } + } + default: + { + PANIC("Unknown PID: 0x%02x\n", request_pid); + } + } + } + else + { + if (response_pid == USB_PID_STALL) + { + LOG_CH32_USBFSH("Data toggle mismatched and STALL\r\n"); + hcd_edpt_clear_stall(0, dev_addr, ep_addr); + edpt_info->data_toggle = 0; + hardware_start_xfer(request_pid, ep_addr, 0); + return; + } + else if (response_pid == USB_PID_NAK) + { + LOG_CH32_USBFSH("Data toggle mismatched and NAK\r\n"); + uint32_t elapsed_time = board_millis() - edpt_info->current_xfer_packet_start_millis; + if (elapsed_time > USB_XFER_TIMEOUT_MILLIS) + { + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + } + else + { + hardware_start_xfer(request_pid, ep_addr, edpt_info->data_toggle); + } + return; + } + else if (response_pid == USB_PID_DATA0 || response_pid == USB_PID_DATA1) + { + LOG_CH32_USBFSH("Data toggle mismatched and DATA0/1 (not STALL). RX_LEN=%d\r\n", USBOTG_H_FS->RX_LEN); + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + return; + } + else + { + LOG_CH32_USBFSH("\r\nIn USBHD_IRQHandler, unexpected response PID: 0x%02x\r\n", response_pid); + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + return; + } + } + } +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) +{ + (void)rhport; + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint8_t ep_num = tu_edpt_number(ep_addr); + uint16_t max_packet_size = ep_desc->wMaxPacketSize; + LOG_CH32_USBFSH("hcd_edpt_open(rhport=%d, dev_addr=0x%02x, %p) EndpointAdderss=0x%02x,maxPacketSize=%d\r\n", rhport, dev_addr, ep_desc, ep_addr, max_packet_size); + + if (ep_num == 0x00) + { + TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x00, max_packet_size) != NULL, false); + TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x80, max_packet_size) != NULL, false); + } + else + { + TU_ASSERT(get_or_add_edpt_record(dev_addr, ep_addr, max_packet_size) != NULL, false); + } + + update_device_address(dev_addr); + + if (dev_addr == 0x00 && ep_num == 0x00) + { + // It assumes first open for the device, so make the port enable + tusb_speed_t device_speed = hcd_port_speed_get(rhport); + update_port_speed(device_speed); + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; + USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; + } + + return true; +} + +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) +{ + (void)rhport; + + usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr); + if (edpt_info == NULL) + { + PANIC("get_edpt_record() returned NULL in hcd_edpt_xfer()\r\n"); + } + + edpt_info->current_xfer_buffer = buffer; + edpt_info->current_xfer_bufferlen = buflen; + + edpt_info->current_xfer_packet_start_millis = board_millis(); + edpt_info->current_xfer_xferred_len = 0; + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) + { + LOG_CH32_USBFSH("hcd_edpt_xfer(): READ, ep_addr=0x%02x, len=%d\r\n", ep_addr, buflen); + return hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); + } + else + { + LOG_CH32_USBFSH("hcd_edpt_xfer(): WRITE, ep_addr=0x%02x, len=%d\r\n", ep_addr, buflen); + USBOTG_H_FS->HOST_TX_LEN = buflen; + memcpy(USBFS_TX_Buf, buffer, buflen); + return hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); + } +} + +bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) +{ + (void) rhport; + (void) dev_addr; + (void) ep_addr; + LOG_CH32_USBFSH("hcd_edpt_abort_xfer(%d, 0x%02x, 0x%02x)\r\n", rhport, dev_addr, ep_addr); + + return false; +} + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) +{ + (void)rhport; + LOG_CH32_USBFSH("hcd_setup_send(rhport=%d, dev_addr=0x%02x, %p)\r\n", rhport, dev_addr, setup_packet); + + + usb_edpt_t* edpt_info_tx = get_edpt_record(dev_addr, 0x00); + usb_edpt_t* edpt_info_rx = get_edpt_record(dev_addr, 0x80); + TU_ASSERT(edpt_info_tx != NULL, false); + TU_ASSERT(edpt_info_rx != NULL, false); + + // Initialize data toggle (SETUP always starts with DATA0) + // Data toggle for OUT is toggled in hcd_int_handler() + edpt_info_tx->data_toggle = 0; + // Data toggle for IN must be set 0x01 manually. + edpt_info_rx->data_toggle = 0x01; + const uint16_t setup_packet_datalen = 8; + memcpy(USBFS_TX_Buf, setup_packet, setup_packet_datalen); + USBOTG_H_FS->HOST_TX_LEN = setup_packet_datalen; + + edpt_info_tx->current_xfer_packet_start_millis = board_millis(); + edpt_info_tx->current_xfer_buffer = USBFS_TX_Buf; + edpt_info_tx->current_xfer_bufferlen = setup_packet_datalen; + edpt_info_tx->current_xfer_xferred_len = 0; + + hardware_start_xfer(USB_PID_SETUP, 0, 0); + + return true; +} + +bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) +{ + (void) rhport; + (void) dev_addr; + LOG_CH32_USBFSH("hcd_edpt_clear_stall(rhport=%d, dev_addr=0x%02x, ep_addr=0x%02x)\r\n", rhport, dev_addr, ep_addr); + // PANIC("\r\nstall\r\n"); + uint8_t edpt_num = tu_edpt_number(ep_addr); + uint8_t setup_request_clear_stall[8] = { + 0x02, 0x01, 0x00, 0x00, edpt_num, 0x00, 0x00, 0x00 + }; + memcpy(USBFS_TX_Buf, setup_request_clear_stall, 8); + USBOTG_H_FS->HOST_TX_LEN = 8; + + hcd_int_disable(0); + + USBOTG_H_FS->HOST_EP_PID = (USB_PID_SETUP << 4) | 0x00; + USBOTG_H_FS->INT_FG |= USBFS_UIF_TRANSFER; + while ((USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER) == 0) { } + USBOTG_H_FS->HOST_EP_PID = 0; + uint8_t response_pid = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK; + (void)response_pid; + LOG_CH32_USBFSH("hcd_edpt_clear_stall() response pid=0x%02x\r\n", response_pid); + + hcd_int_enable(0); + + return true; +} + +#endif From dc3e6a59a9f50182c09e6301a4f8fcc9a4089722 Mon Sep 17 00:00:00 2001 From: verylowfreq <60875431+verylowfreq@users.noreply.github.com> Date: Mon, 9 Sep 2024 19:00:46 +0900 Subject: [PATCH 063/382] Repeat xfer on USB_PID_OUT if data is larger than MaxPacketSize --- src/portable/wch/hcd_ch32_usbfs.c | 34 ++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index 534edb22b..93c5ce519 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -405,9 +405,28 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) case USB_PID_SETUP: case USB_PID_OUT: { - uint16_t xferred_len = edpt_info->current_xfer_bufferlen; - hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); - return; + uint16_t tx_len = USBOTG_H_FS->HOST_TX_LEN; + edpt_info->current_xfer_bufferlen -= tx_len; + edpt_info->current_xfer_xferred_len += tx_len; + if (edpt_info->current_xfer_bufferlen == 0) + { + LOG_CH32_USBFSH("USB_PID_OUT completed %d bytes\r\n", edpt_info->current_xfer_xferred_len); + hcd_event_xfer_complete(dev_addr, ep_addr, edpt_info->current_xfer_xferred_len, XFER_RESULT_SUCCESS, true); + return; + } + else + { + LOG_CH32_USBFSH("USB_PID_OUT continue...\r\n"); + edpt_info->current_xfer_buffer += tx_len; + uint16_t copylen = USBFS_TX_BUF_LEN; + if (copylen > edpt_info->current_xfer_bufferlen) + { + copylen = edpt_info->current_xfer_bufferlen; + } + memcpy(USBFS_TX_Buf, edpt_info->current_xfer_buffer, copylen); + hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); + return; + } } case USB_PID_IN: { @@ -541,8 +560,13 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * else { LOG_CH32_USBFSH("hcd_edpt_xfer(): WRITE, ep_addr=0x%02x, len=%d\r\n", ep_addr, buflen); - USBOTG_H_FS->HOST_TX_LEN = buflen; - memcpy(USBFS_TX_Buf, buffer, buflen); + uint16_t copylen = USBFS_TX_BUF_LEN; + if (copylen > buflen) + { + copylen = buflen; + } + USBOTG_H_FS->HOST_TX_LEN = copylen; + memcpy(USBFS_TX_Buf, buffer, copylen); return hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); } } From 879f78a91df08f0b3c6df7f56d6dd2293455dbcd Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 11 Sep 2024 18:34:48 +0700 Subject: [PATCH 064/382] fix pre-commmit --- src/portable/wch/hcd_ch32_usbfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index 93c5ce519..b775d6eee 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -186,7 +186,7 @@ static void hardware_init_host(bool enabled) static bool hardware_start_xfer(uint8_t pid, uint8_t ep_addr, uint8_t data_toggle) { - LOG_CH32_USBFSH("hardware_start_xfer(pid=%s(0x%02x), ep_addr=0x%02x, toggle=%d)\r\n", + LOG_CH32_USBFSH("hardware_start_xfer(pid=%s(0x%02x), ep_addr=0x%02x, toggle=%d)\r\n", pid == USB_PID_IN ? "IN" : pid == USB_PID_OUT ? "OUT" : pid == USB_PID_SETUP ? "SETUP" : "(other)", pid, ep_addr, data_toggle); @@ -342,7 +342,7 @@ void hcd_int_disable(uint8_t rhport) { (void)rhport; NVIC_DisableIRQ(USBFS_IRQn); - + return; } @@ -492,7 +492,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) } else { - LOG_CH32_USBFSH("\r\nIn USBHD_IRQHandler, unexpected response PID: 0x%02x\r\n", response_pid); + LOG_CH32_USBFSH("In USBHD_IRQHandler, unexpected response PID: 0x%02x\r\n", response_pid); hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); return; } @@ -616,7 +616,7 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) (void) rhport; (void) dev_addr; LOG_CH32_USBFSH("hcd_edpt_clear_stall(rhport=%d, dev_addr=0x%02x, ep_addr=0x%02x)\r\n", rhport, dev_addr, ep_addr); - // PANIC("\r\nstall\r\n"); + // PANIC("\r\install\r\n"); uint8_t edpt_num = tu_edpt_number(ep_addr); uint8_t setup_request_clear_stall[8] = { 0x02, 0x01, 0x00, 0x00, edpt_num, 0x00, 0x00, 0x00 From 7ed5503a5c2bc0b755d97303064614275e74ffb2 Mon Sep 17 00:00:00 2001 From: verylowfreq <60875431+verylowfreq@users.noreply.github.com> Date: Wed, 11 Sep 2024 23:25:49 +0900 Subject: [PATCH 065/382] Fix the condition related to CFG_TUH_WCH_USBIP_USBFS macro --- hw/bsp/ch32v20x/family.c | 2 +- src/portable/wch/hcd_ch32_usbfs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index 8a9ee6819..d674ccd6f 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -32,7 +32,7 @@ void USBHD_IRQHandler(void) { #if CFG_TUD_WCH_USBIP_USBFS tud_int_handler(0); #endif - #if CFG_TUH_WCH_USBIP_USBFS + #if defined(CFG_TUH_WCH_USBIP_USBFS) && CFG_TUH_WCH_USBIP_USBFS tuh_int_handler(0); #endif } diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index b775d6eee..7e73f686f 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if CFG_TUH_ENABLED && defined(TUP_USBIP_WCH_USBFS) && CFG_TUH_WCH_USBIP_USBFS +#if CFG_TUH_ENABLED && defined(TUP_USBIP_WCH_USBFS) && defined(CFG_TUH_WCH_USBIP_USBFS) && CFG_TUH_WCH_USBIP_USBFS #include "host/hcd.h" #include "host/usbh.h" From 382dcca5d63c9eff5ade0cf402fc113c68a57857 Mon Sep 17 00:00:00 2001 From: verylowfreq <60875431+verylowfreq@users.noreply.github.com> Date: Wed, 11 Sep 2024 23:33:19 +0900 Subject: [PATCH 066/382] Update ch32v20x family.cmake --- hw/bsp/ch32v20x/family.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake index a5976e0ea..6092abc8d 100644 --- a/hw/bsp/ch32v20x/family.cmake +++ b/hw/bsp/ch32v20x/family.cmake @@ -61,6 +61,7 @@ function(add_board_target BOARD_TARGET) if (PORT EQUAL 0) target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUD_WCH_USBIP_FSDEV=1 + CFG_TUH_WCH_USBIP_USBFS=1 ) elseif (PORT EQUAL 1) target_compile_definitions(${BOARD_TARGET} PUBLIC @@ -127,6 +128,7 @@ function(family_configure_example TARGET RTOS) target_sources(${TARGET} PUBLIC ${TOP}/src/portable/wch/dcd_ch32_usbfs.c + ${TOP}/src/portable/wch/hcd_ch32_usbfs.c ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ) target_link_libraries(${TARGET} PUBLIC board_${BOARD}) From 426588d947b5c9ac789571019fc2b8da5d756669 Mon Sep 17 00:00:00 2001 From: verylowfreq <60875431+verylowfreq@users.noreply.github.com> Date: Mon, 28 Oct 2024 21:28:15 +0900 Subject: [PATCH 067/382] Fix for timing, timeout, and device switching issues --- src/portable/wch/hcd_ch32_usbfs.c | 193 ++++++++++++++++++++---------- 1 file changed, 127 insertions(+), 66 deletions(-) diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index 7e73f686f..ddd366b4f 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -43,24 +43,26 @@ __attribute__((aligned(4))) static uint8_t USBFS_RX_Buf[USBFS_RX_BUF_LEN]; __attribute__((aligned(4))) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN]; -#define USB_XFER_TIMEOUT_MILLIS 500 +#define USB_XFER_TIMEOUT_MILLIS 100 +#define USB_INTERRUPT_XFER_TIMEOUT_MILLIS 1 #define PANIC(...) do { printf("\r\nPANIC: " __VA_ARGS__); while (true) { } } while (false) #define LOG_CH32_USBFSH(...) TU_LOG3(__VA_ARGS__) // Busywait for delay microseconds/nanoseconds -// static void loopdelay(uint32_t count) -// { -// volatile uint32_t c = count / 3; -// // while (c-- != 0); -// asm volatile( -// "1: \n" // loop label -// " addi %0, %0, -1 \n" // c-- -// " bne %0, zero, 1b \n" // if (c != 0) goto loop -// : "+r"(c) // c is input/output operand -// ); -// } +static void loopdelay(uint32_t count) +{ + volatile uint32_t c = count / 3; + if (c == 0) { return; } + // while (c-- != 0); + asm volatile( + "1: \n" // loop label + " addi %0, %0, -1 \n" // c-- + " bne %0, zero, 1b \n" // if (c != 0) goto loop + : "+r"(c) // c is input/output operand + ); +} // Endpoint status @@ -71,21 +73,30 @@ typedef struct usb_edpt uint8_t dev_addr; uint8_t ep_addr; - uint16_t max_packet_size; + uint8_t max_packet_size; + + uint8_t xfer_type; // Data toggle (0 or not 0) for DATA0/1 uint8_t data_toggle; +} usb_edpt_t; + +static usb_edpt_t usb_edpt_list[CFG_TUH_DEVICE_MAX * 6] = {}; + + +typedef struct usb_current_xfer_st { + bool is_busy; + uint8_t dev_addr; + uint8_t ep_addr; // Xfer started time in millis for timeout uint32_t current_xfer_packet_start_millis; uint8_t* current_xfer_buffer; uint16_t current_xfer_bufferlen; uint16_t current_xfer_xferred_len; +} usb_current_xfer_t; -} usb_edpt_t; - - -static usb_edpt_t usb_edpt_list[8] = { }; +static volatile usb_current_xfer_t usb_current_xfer_info = {}; static usb_edpt_t* get_edpt_record(uint8_t dev_addr, uint8_t ep_addr) @@ -113,26 +124,26 @@ static usb_edpt_t* get_empty_record_slot(void) return NULL; } -static usb_edpt_t* add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size) +static usb_edpt_t* add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type) { usb_edpt_t* slot = get_empty_record_slot(); + if (slot == NULL) { + PANIC("add_edpt_record(0x%02x, 0x%02x, ...) no slot for new record\r\n", dev_addr, ep_addr); + } TU_ASSERT(slot != NULL, NULL); slot->dev_addr = dev_addr; slot->ep_addr = ep_addr; slot->max_packet_size = max_packet_size; + slot->xfer_type = xfer_type; slot->data_toggle = 0; - slot->current_xfer_packet_start_millis = 0; - slot->current_xfer_buffer = NULL; - slot->current_xfer_bufferlen = 0; - slot->current_xfer_xferred_len = 0; slot->configured = true; return slot; } -static usb_edpt_t* get_or_add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size) +static usb_edpt_t* get_or_add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type) { usb_edpt_t* ret = get_edpt_record(dev_addr, ep_addr); if (ret != NULL) @@ -141,7 +152,7 @@ static usb_edpt_t* get_or_add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uin } else { - return add_edpt_record(dev_addr, ep_addr, max_packet_size); + return add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type); } } @@ -157,6 +168,17 @@ static void remove_edpt_record_for_device(uint8_t dev_addr) } } +// static void dump_edpt_record_list() { +// for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) { +// usb_edpt_t* cur = &usb_edpt_list[i]; +// if (cur->configured) { +// printf("[%2d] Device 0x%02x Endpoint 0x%02x\r\n", i, cur->dev_addr, cur->ep_addr); +// } else { +// printf("[%2d] not configured\r\n", i); +// } +// } +// } + /** Enable or disable USBFS Host function */ static void hardware_init_host(bool enabled) @@ -180,7 +202,8 @@ static void hardware_init_host(bool enabled) USBOTG_H_FS->HOST_EP_MOD = USBFS_UH_EP_TX_EN | USBFS_UH_EP_RX_EN; USBOTG_H_FS->HOST_RX_DMA = (uint32_t)USBFS_RX_Buf; USBOTG_H_FS->HOST_TX_DMA = (uint32_t)USBFS_TX_Buf; - USBOTG_H_FS->INT_EN = USBFS_UIE_TRANSFER | USBFS_UIE_DETECT; + // USBOTG_H_FS->INT_EN = USBFS_UIE_TRANSFER | USBFS_UIE_DETECT; + USBOTG_H_FS->INT_EN = USBFS_UIE_DETECT; } } @@ -199,6 +222,7 @@ static bool hardware_start_xfer(uint8_t pid, uint8_t ep_addr, uint8_t data_toggl USBOTG_H_FS->HOST_TX_CTRL = (data_toggle != 0) ? USBFS_UH_T_TOG : 0; USBOTG_H_FS->HOST_RX_CTRL = (data_toggle != 0) ? USBFS_UH_R_TOG : 0; USBOTG_H_FS->HOST_EP_PID = pid_edpt; + USBOTG_H_FS->INT_EN |= USBFS_UIE_TRANSFER; USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; return true; } @@ -371,19 +395,21 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) if (USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER) { + // Disable transfer interrupt + USBOTG_H_FS->INT_EN &= ~USBFS_UIE_TRANSFER; + // Clear the flag + // USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; // Copy PID and Endpoint uint8_t pid_edpt = USBOTG_H_FS->HOST_EP_PID; uint8_t status = USBOTG_H_FS->INT_ST; + uint8_t dev_addr = USBOTG_H_FS->DEV_ADDR & USBFS_USB_ADDR_MASK; // Clear register to stop transfer - USBOTG_H_FS->HOST_EP_PID = 0; - // Clear the flag - USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; + // USBOTG_H_FS->HOST_EP_PID = 0x00; LOG_CH32_USBFSH("hcd_int_handler() pid_edpt=0x%02x\r\n", pid_edpt); uint8_t request_pid = pid_edpt >> 4; - uint8_t response_pid = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK; - uint8_t dev_addr = USBOTG_H_FS->DEV_ADDR; + uint8_t response_pid = status & USBFS_UIS_H_RES_MASK; uint8_t ep_addr = pid_edpt & 0x0f; if (request_pid == USB_PID_IN) { @@ -393,7 +419,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr); if (edpt_info == NULL) { - PANIC("\r\nget_edpt_record() returned NULL in USBHD_IRQHandler\r\n"); + PANIC("\r\nget_edpt_record(0x%02x, 0x%02x) returned NULL in USBHD_IRQHandler\r\n", dev_addr, ep_addr); } if (status & USBFS_UIS_TOG_OK) @@ -406,24 +432,25 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) case USB_PID_OUT: { uint16_t tx_len = USBOTG_H_FS->HOST_TX_LEN; - edpt_info->current_xfer_bufferlen -= tx_len; - edpt_info->current_xfer_xferred_len += tx_len; - if (edpt_info->current_xfer_bufferlen == 0) + usb_current_xfer_info.current_xfer_bufferlen -= tx_len; + usb_current_xfer_info.current_xfer_xferred_len += tx_len; + if (usb_current_xfer_info.current_xfer_bufferlen == 0) { - LOG_CH32_USBFSH("USB_PID_OUT completed %d bytes\r\n", edpt_info->current_xfer_xferred_len); - hcd_event_xfer_complete(dev_addr, ep_addr, edpt_info->current_xfer_xferred_len, XFER_RESULT_SUCCESS, true); + LOG_CH32_USBFSH("USB_PID_%s completed %d bytes\r\n", request_pid == USB_PID_OUT ? "OUT" : "SETUP", usb_current_xfer_info.current_xfer_xferred_len); + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, usb_current_xfer_info.current_xfer_xferred_len, XFER_RESULT_SUCCESS, true); return; } else { LOG_CH32_USBFSH("USB_PID_OUT continue...\r\n"); - edpt_info->current_xfer_buffer += tx_len; + usb_current_xfer_info.current_xfer_buffer += tx_len; uint16_t copylen = USBFS_TX_BUF_LEN; - if (copylen > edpt_info->current_xfer_bufferlen) + if (copylen > usb_current_xfer_info.current_xfer_bufferlen) { - copylen = edpt_info->current_xfer_bufferlen; + copylen = usb_current_xfer_info.current_xfer_bufferlen; } - memcpy(USBFS_TX_Buf, edpt_info->current_xfer_buffer, copylen); + memcpy(USBFS_TX_Buf, usb_current_xfer_info.current_xfer_buffer, copylen); hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); return; } @@ -431,18 +458,19 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) case USB_PID_IN: { uint16_t received_len = USBOTG_H_FS->RX_LEN; - edpt_info->current_xfer_xferred_len += received_len; - uint16_t xferred_len = edpt_info->current_xfer_xferred_len; + usb_current_xfer_info.current_xfer_xferred_len += received_len; + uint16_t xferred_len = usb_current_xfer_info.current_xfer_xferred_len; LOG_CH32_USBFSH("Read %d bytes\r\n", received_len); - // if (received_len > 0 && (edpt_info->current_xfer_buffer == NULL || edpt_info->current_xfer_bufferlen == 0)) { + // if (received_len > 0 && (usb_current_xfer_info.current_xfer_buffer == NULL || usb_current_xfer_info.current_xfer_bufferlen == 0)) { // PANIC("Data received but buffer not set\r\n"); // } - memcpy(edpt_info->current_xfer_buffer, USBFS_RX_Buf, received_len); - edpt_info->current_xfer_buffer += received_len; - if ((received_len < edpt_info->max_packet_size) || (xferred_len == edpt_info->current_xfer_bufferlen)) + memcpy(usb_current_xfer_info.current_xfer_buffer, USBFS_RX_Buf, received_len); + usb_current_xfer_info.current_xfer_buffer += received_len; + if ((received_len < edpt_info->max_packet_size) || (xferred_len == usb_current_xfer_info.current_xfer_bufferlen)) { // USB device sent all data. LOG_CH32_USBFSH("USB_PID_IN completed\r\n"); + usb_current_xfer_info.is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); return; } @@ -464,7 +492,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { if (response_pid == USB_PID_STALL) { - LOG_CH32_USBFSH("Data toggle mismatched and STALL\r\n"); + LOG_CH32_USBFSH("STALL response\r\n"); hcd_edpt_clear_stall(0, dev_addr, ep_addr); edpt_info->data_toggle = 0; hardware_start_xfer(request_pid, ep_addr, 0); @@ -472,10 +500,16 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) } else if (response_pid == USB_PID_NAK) { - LOG_CH32_USBFSH("Data toggle mismatched and NAK\r\n"); - uint32_t elapsed_time = board_millis() - edpt_info->current_xfer_packet_start_millis; - if (elapsed_time > USB_XFER_TIMEOUT_MILLIS) + LOG_CH32_USBFSH("NAK reposense\r\n"); + uint32_t elapsed_time = board_millis() - usb_current_xfer_info.current_xfer_packet_start_millis; + if (edpt_info->xfer_type == TUSB_XFER_INTERRUPT && (elapsed_time > USB_INTERRUPT_XFER_TIMEOUT_MILLIS)) { + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, true); + } + else if (elapsed_time > USB_XFER_TIMEOUT_MILLIS) + { + usb_current_xfer_info.is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); } else @@ -487,12 +521,14 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) else if (response_pid == USB_PID_DATA0 || response_pid == USB_PID_DATA1) { LOG_CH32_USBFSH("Data toggle mismatched and DATA0/1 (not STALL). RX_LEN=%d\r\n", USBOTG_H_FS->RX_LEN); + usb_current_xfer_info.is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); return; } else { LOG_CH32_USBFSH("In USBHD_IRQHandler, unexpected response PID: 0x%02x\r\n", response_pid); + usb_current_xfer_info.is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); return; } @@ -510,16 +546,17 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const uint8_t ep_addr = ep_desc->bEndpointAddress; uint8_t ep_num = tu_edpt_number(ep_addr); uint16_t max_packet_size = ep_desc->wMaxPacketSize; - LOG_CH32_USBFSH("hcd_edpt_open(rhport=%d, dev_addr=0x%02x, %p) EndpointAdderss=0x%02x,maxPacketSize=%d\r\n", rhport, dev_addr, ep_desc, ep_addr, max_packet_size); + uint8_t xfer_type = ep_desc->bmAttributes.xfer; + LOG_CH32_USBFSH("hcd_edpt_open(rhport=%d, dev_addr=0x%02x, %p) EndpointAdderss=0x%02x,maxPacketSize=%d,xfer_type=%d\r\n", rhport, dev_addr, ep_desc, ep_addr, max_packet_size, xfer_type); if (ep_num == 0x00) { - TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x00, max_packet_size) != NULL, false); - TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x80, max_packet_size) != NULL, false); + TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x00, max_packet_size, xfer_type) != NULL, false); + TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x80, max_packet_size, xfer_type) != NULL, false); } else { - TU_ASSERT(get_or_add_edpt_record(dev_addr, ep_addr, max_packet_size) != NULL, false); + TU_ASSERT(get_or_add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type) != NULL, false); } update_device_address(dev_addr); @@ -540,26 +577,36 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * { (void)rhport; + while (usb_current_xfer_info.is_busy) { + osal_task_delay(1); + } + usb_current_xfer_info.is_busy = true; + usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr); if (edpt_info == NULL) { PANIC("get_edpt_record() returned NULL in hcd_edpt_xfer()\r\n"); } + + update_device_address(dev_addr); + tusb_speed_t device_speed = hcd_port_speed_get(rhport); + update_port_speed(device_speed); - edpt_info->current_xfer_buffer = buffer; - edpt_info->current_xfer_bufferlen = buflen; - - edpt_info->current_xfer_packet_start_millis = board_millis(); - edpt_info->current_xfer_xferred_len = 0; + usb_current_xfer_info.dev_addr = dev_addr; + usb_current_xfer_info.ep_addr = ep_addr; + usb_current_xfer_info.current_xfer_buffer = buffer; + usb_current_xfer_info.current_xfer_bufferlen = buflen; + usb_current_xfer_info.current_xfer_packet_start_millis = board_millis(); + usb_current_xfer_info.current_xfer_xferred_len = 0; if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { - LOG_CH32_USBFSH("hcd_edpt_xfer(): READ, ep_addr=0x%02x, len=%d\r\n", ep_addr, buflen); + LOG_CH32_USBFSH("hcd_edpt_xfer(): READ, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); return hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); } else { - LOG_CH32_USBFSH("hcd_edpt_xfer(): WRITE, ep_addr=0x%02x, len=%d\r\n", ep_addr, buflen); + LOG_CH32_USBFSH("hcd_edpt_xfer(): WRITE, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); uint16_t copylen = USBFS_TX_BUF_LEN; if (copylen > buflen) { @@ -584,8 +631,20 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { (void)rhport; + + if (usb_current_xfer_info.is_busy) { + osal_task_delay(1); + } + usb_current_xfer_info.is_busy = true; + LOG_CH32_USBFSH("hcd_setup_send(rhport=%d, dev_addr=0x%02x, %p)\r\n", rhport, dev_addr, setup_packet); + // loopdelay(SystemCoreClock / 1000000 * 100); + loopdelay(1); + + update_device_address(dev_addr); + tusb_speed_t device_speed = hcd_port_speed_get(rhport); + update_port_speed(device_speed); usb_edpt_t* edpt_info_tx = get_edpt_record(dev_addr, 0x00); usb_edpt_t* edpt_info_rx = get_edpt_record(dev_addr, 0x80); @@ -600,11 +659,13 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet const uint16_t setup_packet_datalen = 8; memcpy(USBFS_TX_Buf, setup_packet, setup_packet_datalen); USBOTG_H_FS->HOST_TX_LEN = setup_packet_datalen; - - edpt_info_tx->current_xfer_packet_start_millis = board_millis(); - edpt_info_tx->current_xfer_buffer = USBFS_TX_Buf; - edpt_info_tx->current_xfer_bufferlen = setup_packet_datalen; - edpt_info_tx->current_xfer_xferred_len = 0; + uint8_t ep_addr = (setup_packet[0] & 0x80) ? 0x80 : 0x00; + usb_current_xfer_info.dev_addr = dev_addr; + usb_current_xfer_info.ep_addr = ep_addr; + usb_current_xfer_info.current_xfer_packet_start_millis = board_millis(); + usb_current_xfer_info.current_xfer_buffer = USBFS_TX_Buf; + usb_current_xfer_info.current_xfer_bufferlen = setup_packet_datalen; + usb_current_xfer_info.current_xfer_xferred_len = 0; hardware_start_xfer(USB_PID_SETUP, 0, 0); From 9ca4bc89a7e285796e8102eb7a8fd1bbc6fb9938 Mon Sep 17 00:00:00 2001 From: verylowfreq <60875431+verylowfreq@users.noreply.github.com> Date: Thu, 12 Dec 2024 09:53:58 +0900 Subject: [PATCH 068/382] Update hcd_init() signature. Add osal_task_delay() implementation for none os. --- src/portable/wch/hcd_ch32_usbfs.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index ddd366b4f..cbbf90da6 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -37,6 +37,10 @@ #include "ch32v20x.h" #include "ch32v20x_usb.h" +void osal_task_delay(uint32_t msec) { + unsigned long start = board_millis(); + while (board_millis() - start < msec) {} +} #define USBFS_RX_BUF_LEN 64 #define USBFS_TX_BUF_LEN 64 @@ -264,9 +268,10 @@ static bool hardware_device_attached(void) //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ -bool hcd_init(uint8_t rhport) +bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { (void)rhport; + (void)rh_init; hardware_init_host(true); return true; From cd2b3a53217857930bd8519d074b355ae8933982 Mon Sep 17 00:00:00 2001 From: verylowfreq <60875431+verylowfreq@users.noreply.github.com> Date: Sun, 16 Mar 2025 10:06:27 +0900 Subject: [PATCH 069/382] Fix interupt, LowSpeed switching and rename --- src/portable/wch/hcd_ch32_usbfs.c | 204 ++++++++++++++++-------------- 1 file changed, 111 insertions(+), 93 deletions(-) diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index cbbf90da6..800390989 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -38,7 +38,7 @@ #include "ch32v20x_usb.h" void osal_task_delay(uint32_t msec) { - unsigned long start = board_millis(); + uint32_t start = board_millis(); while (board_millis() - start < msec) {} } @@ -48,25 +48,25 @@ __attribute__((aligned(4))) static uint8_t USBFS_RX_Buf[USBFS_RX_BUF_LEN]; __attribute__((aligned(4))) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN]; #define USB_XFER_TIMEOUT_MILLIS 100 -#define USB_INTERRUPT_XFER_TIMEOUT_MILLIS 1 +// #define USB_INTERRUPT_XFER_TIMEOUT_MILLIS 1 -#define PANIC(...) do { printf("\r\nPANIC: " __VA_ARGS__); while (true) { } } while (false) +#define PANIC(...) do { printf("%s() L%d: ", __func__, __LINE__); printf("\r\n[PANIC] " __VA_ARGS__); while (true) { } } while (false) #define LOG_CH32_USBFSH(...) TU_LOG3(__VA_ARGS__) // Busywait for delay microseconds/nanoseconds -static void loopdelay(uint32_t count) -{ - volatile uint32_t c = count / 3; - if (c == 0) { return; } - // while (c-- != 0); - asm volatile( - "1: \n" // loop label - " addi %0, %0, -1 \n" // c-- - " bne %0, zero, 1b \n" // if (c != 0) goto loop - : "+r"(c) // c is input/output operand - ); -} +// static void loopdelay(uint32_t count) +// { +// volatile uint32_t c = count / 3; +// if (c == 0) { return; } +// // while (c-- != 0); +// asm volatile( +// "1: \n" // loop label +// " addi %0, %0, -1 \n" // c-- +// " bne %0, zero, 1b \n" // if (c != 0) goto loop +// : "+r"(c) // c is input/output operand +// ); +// } // Endpoint status @@ -94,10 +94,10 @@ typedef struct usb_current_xfer_st { uint8_t dev_addr; uint8_t ep_addr; // Xfer started time in millis for timeout - uint32_t current_xfer_packet_start_millis; - uint8_t* current_xfer_buffer; - uint16_t current_xfer_bufferlen; - uint16_t current_xfer_xferred_len; + uint32_t start_ms; + uint8_t* buffer; + uint16_t bufferlen; + uint16_t xferred_len; } usb_current_xfer_t; static volatile usb_current_xfer_t usb_current_xfer_info = {}; @@ -184,6 +184,8 @@ static void remove_edpt_record_for_device(uint8_t dev_addr) // } +static bool interrupt_enabled = false; + /** Enable or disable USBFS Host function */ static void hardware_init_host(bool enabled) { @@ -201,7 +203,8 @@ static void hardware_init_host(bool enabled) else { // Enable USB Host features - NVIC_DisableIRQ(USBFS_IRQn); + // NVIC_DisableIRQ(USBFS_IRQn); + hcd_int_disable(0); USBOTG_H_FS->BASE_CTRL = USBFS_UC_HOST_MODE | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN; USBOTG_H_FS->HOST_EP_MOD = USBFS_UH_EP_TX_EN | USBFS_UH_EP_RX_EN; USBOTG_H_FS->HOST_RX_DMA = (uint32_t)USBFS_RX_Buf; @@ -217,10 +220,10 @@ static bool hardware_start_xfer(uint8_t pid, uint8_t ep_addr, uint8_t data_toggl pid == USB_PID_IN ? "IN" : pid == USB_PID_OUT ? "OUT" : pid == USB_PID_SETUP ? "SETUP" : "(other)", pid, ep_addr, data_toggle); - if (pid == USB_PID_IN) - { // FIXME: long delay needed (at release build) about 30msec - // loopdelay(SystemCoreClock / 1000 * 30); - } + // if (pid == USB_PID_IN) + // { // FIXME: long delay needed (at release build) about 30msec + // loopdelay(SystemCoreClock / 1000 * 30); + // } uint8_t pid_edpt = (pid << 4) | (tu_edpt_number(ep_addr) & 0x0f); USBOTG_H_FS->HOST_TX_CTRL = (data_toggle != 0) ? USBFS_UH_T_TOG : 0; @@ -233,16 +236,16 @@ static bool hardware_start_xfer(uint8_t pid, uint8_t ep_addr, uint8_t data_toggl /** Set device address to communicate */ -static void update_device_address(uint8_t dev_addr) +static void hardware_update_device_address(uint8_t dev_addr) { // Keep the bit of GP_BIT. Other 7bits are actual device address. USBOTG_H_FS->DEV_ADDR = (USBOTG_H_FS->DEV_ADDR & USBFS_UDA_GP_BIT) | (dev_addr & USBFS_USB_ADDR_MASK); } /** Set port speed */ -static void update_port_speed(tusb_speed_t speed) +static void hardware_update_port_speed(tusb_speed_t speed) { - LOG_CH32_USBFSH("update_port_speed(%s)\r\n", speed == TUSB_SPEED_FULL ? "Full" : speed == TUSB_SPEED_LOW ? "Low" : "(invalid)"); + LOG_CH32_USBFSH("hardware_update_port_speed(%s)\r\n", speed == TUSB_SPEED_FULL ? "Full" : speed == TUSB_SPEED_LOW ? "Low" : "(invalid)"); switch (speed) { case TUSB_SPEED_LOW: USBOTG_H_FS->BASE_CTRL |= USBFS_UC_LOW_SPEED; @@ -255,10 +258,22 @@ static void update_port_speed(tusb_speed_t speed) USBOTG_H_FS->HOST_SETUP &= ~USBFS_UH_PRE_PID_EN; return; default: - PANIC("update_port_speed(%d)\r\n", speed); + PANIC("hardware_update_port_speed(%d)\r\n", speed); } } + +static void hardware_set_port_address_speed(uint8_t dev_addr) { + hardware_update_device_address(dev_addr); + tusb_speed_t rhport_speed = hcd_port_speed_get(0); + tusb_speed_t dev_speed = tuh_speed_get(dev_addr); + hardware_update_port_speed(dev_speed); + if (rhport_speed == TUSB_SPEED_FULL && dev_speed == TUSB_SPEED_LOW) { + USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED; + } +} + + static bool hardware_device_attached(void) { return USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH; @@ -285,28 +300,21 @@ bool hcd_deinit(uint8_t rhport) return true; } + +static bool int_state_for_portreset = false; + void hcd_port_reset(uint8_t rhport) { (void)rhport; LOG_CH32_USBFSH("hcd_port_reset()\r\n"); - NVIC_DisableIRQ(USBFS_IRQn); - update_device_address( 0x00 ); + int_state_for_portreset = interrupt_enabled; + // NVIC_DisableIRQ(USBFS_IRQn); + hcd_int_disable(rhport); + hardware_update_device_address(0x00); + + // USBOTG_H_FS->HOST_SETUP = 0x00; USBOTG_H_FS->HOST_CTRL |= USBFS_UH_BUS_RESET; - osal_task_delay(15); - USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_BUS_RESET; - osal_task_delay(2); - - if ((USBOTG_H_FS->HOST_CTRL & USBFS_UH_PORT_EN) == 0) - { - if (hcd_port_speed_get(0) == TUSB_SPEED_LOW) - { - update_port_speed(TUSB_SPEED_LOW); - } - } - - USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; - USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; return; } @@ -315,9 +323,27 @@ void hcd_port_reset_end(uint8_t rhport) { (void)rhport; LOG_CH32_USBFSH("hcd_port_reset_end()\r\n"); + + USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_BUS_RESET; + osal_task_delay(2); + + if ((USBOTG_H_FS->HOST_CTRL & USBFS_UH_PORT_EN) == 0) + { + if (hcd_port_speed_get(0) == TUSB_SPEED_LOW) + { + hardware_update_port_speed(TUSB_SPEED_LOW); + } + } + + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; + USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; + // Suppress the attached event USBOTG_H_FS->INT_FG |= USBFS_UIF_DETECT; - NVIC_EnableIRQ(USBFS_IRQn); + + if (int_state_for_portreset) { + hcd_int_enable(rhport); + } return; } @@ -363,6 +389,7 @@ void hcd_int_enable(uint8_t rhport) { (void)rhport; NVIC_EnableIRQ(USBFS_IRQn); + interrupt_enabled = true; return; } @@ -371,6 +398,7 @@ void hcd_int_disable(uint8_t rhport) { (void)rhport; NVIC_DisableIRQ(USBFS_IRQn); + interrupt_enabled = false; return; } @@ -437,25 +465,25 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) case USB_PID_OUT: { uint16_t tx_len = USBOTG_H_FS->HOST_TX_LEN; - usb_current_xfer_info.current_xfer_bufferlen -= tx_len; - usb_current_xfer_info.current_xfer_xferred_len += tx_len; - if (usb_current_xfer_info.current_xfer_bufferlen == 0) + usb_current_xfer_info.bufferlen -= tx_len; + usb_current_xfer_info.xferred_len += tx_len; + if (usb_current_xfer_info.bufferlen == 0) { - LOG_CH32_USBFSH("USB_PID_%s completed %d bytes\r\n", request_pid == USB_PID_OUT ? "OUT" : "SETUP", usb_current_xfer_info.current_xfer_xferred_len); + LOG_CH32_USBFSH("USB_PID_%s completed %d bytes\r\n", request_pid == USB_PID_OUT ? "OUT" : "SETUP", usb_current_xfer_info.xferred_len); usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, usb_current_xfer_info.current_xfer_xferred_len, XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(dev_addr, ep_addr, usb_current_xfer_info.xferred_len, XFER_RESULT_SUCCESS, true); return; } else { LOG_CH32_USBFSH("USB_PID_OUT continue...\r\n"); - usb_current_xfer_info.current_xfer_buffer += tx_len; + usb_current_xfer_info.buffer += tx_len; uint16_t copylen = USBFS_TX_BUF_LEN; - if (copylen > usb_current_xfer_info.current_xfer_bufferlen) + if (copylen > usb_current_xfer_info.bufferlen) { - copylen = usb_current_xfer_info.current_xfer_bufferlen; + copylen = usb_current_xfer_info.bufferlen; } - memcpy(USBFS_TX_Buf, usb_current_xfer_info.current_xfer_buffer, copylen); + memcpy(USBFS_TX_Buf, usb_current_xfer_info.buffer, copylen); hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); return; } @@ -463,15 +491,15 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) case USB_PID_IN: { uint16_t received_len = USBOTG_H_FS->RX_LEN; - usb_current_xfer_info.current_xfer_xferred_len += received_len; - uint16_t xferred_len = usb_current_xfer_info.current_xfer_xferred_len; + usb_current_xfer_info.xferred_len += received_len; + uint16_t xferred_len = usb_current_xfer_info.xferred_len; LOG_CH32_USBFSH("Read %d bytes\r\n", received_len); - // if (received_len > 0 && (usb_current_xfer_info.current_xfer_buffer == NULL || usb_current_xfer_info.current_xfer_bufferlen == 0)) { + // if (received_len > 0 && (usb_current_xfer_info.buffer == NULL || usb_current_xfer_info.bufferlen == 0)) { // PANIC("Data received but buffer not set\r\n"); // } - memcpy(usb_current_xfer_info.current_xfer_buffer, USBFS_RX_Buf, received_len); - usb_current_xfer_info.current_xfer_buffer += received_len; - if ((received_len < edpt_info->max_packet_size) || (xferred_len == usb_current_xfer_info.current_xfer_bufferlen)) + memcpy(usb_current_xfer_info.buffer, USBFS_RX_Buf, received_len); + usb_current_xfer_info.buffer += received_len; + if ((received_len < edpt_info->max_packet_size) || (xferred_len == usb_current_xfer_info.bufferlen)) { // USB device sent all data. LOG_CH32_USBFSH("USB_PID_IN completed\r\n"); @@ -506,8 +534,8 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) else if (response_pid == USB_PID_NAK) { LOG_CH32_USBFSH("NAK reposense\r\n"); - uint32_t elapsed_time = board_millis() - usb_current_xfer_info.current_xfer_packet_start_millis; - if (edpt_info->xfer_type == TUSB_XFER_INTERRUPT && (elapsed_time > USB_INTERRUPT_XFER_TIMEOUT_MILLIS)) + uint32_t elapsed_time = board_millis() - usb_current_xfer_info.start_ms; + if (edpt_info->xfer_type == TUSB_XFER_INTERRUPT) { usb_current_xfer_info.is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, true); @@ -564,16 +592,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const TU_ASSERT(get_or_add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type) != NULL, false); } - update_device_address(dev_addr); - if (dev_addr == 0x00 && ep_num == 0x00) - { - // It assumes first open for the device, so make the port enable - tusb_speed_t device_speed = hcd_port_speed_get(rhport); - update_port_speed(device_speed); USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; - } + + hardware_set_port_address_speed(dev_addr); return true; } @@ -582,9 +605,10 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * { (void)rhport; - while (usb_current_xfer_info.is_busy) { - osal_task_delay(1); - } + LOG_CH32_USBFSH("hcd_edpt_xfer(%d, 0x%02x, 0x%02x, ...)\r\n", rhport, dev_addr, ep_addr); + + while (usb_current_xfer_info.is_busy) { } + usb_current_xfer_info.is_busy = true; usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr); @@ -593,16 +617,14 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * PANIC("get_edpt_record() returned NULL in hcd_edpt_xfer()\r\n"); } - update_device_address(dev_addr); - tusb_speed_t device_speed = hcd_port_speed_get(rhport); - update_port_speed(device_speed); + hardware_set_port_address_speed(dev_addr); usb_current_xfer_info.dev_addr = dev_addr; usb_current_xfer_info.ep_addr = ep_addr; - usb_current_xfer_info.current_xfer_buffer = buffer; - usb_current_xfer_info.current_xfer_bufferlen = buflen; - usb_current_xfer_info.current_xfer_packet_start_millis = board_millis(); - usb_current_xfer_info.current_xfer_xferred_len = 0; + usb_current_xfer_info.buffer = buffer; + usb_current_xfer_info.bufferlen = buflen; + usb_current_xfer_info.start_ms = board_millis(); + usb_current_xfer_info.xferred_len = 0; if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { @@ -628,7 +650,6 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) (void) rhport; (void) dev_addr; (void) ep_addr; - LOG_CH32_USBFSH("hcd_edpt_abort_xfer(%d, 0x%02x, 0x%02x)\r\n", rhport, dev_addr, ep_addr); return false; } @@ -637,19 +658,13 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet { (void)rhport; - if (usb_current_xfer_info.is_busy) { - osal_task_delay(1); - } + while (usb_current_xfer_info.is_busy) { } + usb_current_xfer_info.is_busy = true; LOG_CH32_USBFSH("hcd_setup_send(rhport=%d, dev_addr=0x%02x, %p)\r\n", rhport, dev_addr, setup_packet); - // loopdelay(SystemCoreClock / 1000000 * 100); - loopdelay(1); - - update_device_address(dev_addr); - tusb_speed_t device_speed = hcd_port_speed_get(rhport); - update_port_speed(device_speed); + hardware_set_port_address_speed(dev_addr); usb_edpt_t* edpt_info_tx = get_edpt_record(dev_addr, 0x00); usb_edpt_t* edpt_info_rx = get_edpt_record(dev_addr, 0x80); @@ -667,10 +682,10 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet uint8_t ep_addr = (setup_packet[0] & 0x80) ? 0x80 : 0x00; usb_current_xfer_info.dev_addr = dev_addr; usb_current_xfer_info.ep_addr = ep_addr; - usb_current_xfer_info.current_xfer_packet_start_millis = board_millis(); - usb_current_xfer_info.current_xfer_buffer = USBFS_TX_Buf; - usb_current_xfer_info.current_xfer_bufferlen = setup_packet_datalen; - usb_current_xfer_info.current_xfer_xferred_len = 0; + usb_current_xfer_info.start_ms = board_millis(); + usb_current_xfer_info.buffer = USBFS_TX_Buf; + usb_current_xfer_info.bufferlen = setup_packet_datalen; + usb_current_xfer_info.xferred_len = 0; hardware_start_xfer(USB_PID_SETUP, 0, 0); @@ -690,6 +705,7 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) memcpy(USBFS_TX_Buf, setup_request_clear_stall, 8); USBOTG_H_FS->HOST_TX_LEN = 8; + bool prev_int_state = interrupt_enabled; hcd_int_disable(0); USBOTG_H_FS->HOST_EP_PID = (USB_PID_SETUP << 4) | 0x00; @@ -700,7 +716,9 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) (void)response_pid; LOG_CH32_USBFSH("hcd_edpt_clear_stall() response pid=0x%02x\r\n", response_pid); + if (prev_int_state) { hcd_int_enable(0); + } return true; } From e0df20f260a6c5d5e347427e9e57e73f9327f8d0 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Mon, 17 Mar 2025 12:20:49 +0700 Subject: [PATCH 070/382] change pio-usb to upstream --- tools/get_deps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/get_deps.py b/tools/get_deps.py index b82abac4f..3f529bd7e 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -58,8 +58,8 @@ deps_optional = { 'hw/mcu/nxp/mcux-sdk': ['https://github.com/hathach/mcux-sdk.git', '144f1eb7ea8c06512e12f12b27383601c0272410', 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'], - 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/hathach/Pico-PIO-USB.git', - '9c8df3083b62c0a678f3bd3d8a7e773932622d4b', + 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/sekigon-gonnoc/Pico-PIO-USB.git', + '0ca3657d55ea20e7fa4483bbd21ce951bc1d6fa5', 'rp2040'], 'hw/mcu/renesas/fsp': ['https://github.com/renesas/fsp.git', 'edcc97d684b6f716728a60d7a6fea049d9870bd6', From 31b3a2f63bcf4f1969ada9d0c099444959b37388 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Sat, 15 Mar 2025 11:20:57 -0700 Subject: [PATCH 071/382] Fix 3031: implement tuh_midi_itf_get_info() --- src/class/midi/midi_host.c | 23 +++++++++++++++++++++++ src/class/midi/midi_host.h | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 4d824e04c..9019d476b 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -346,6 +346,29 @@ uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num) { return TUSB_INDEX_INVALID_8; } +bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) +{ + midih_interface_t* p_midi = &_midi_host[idx]; + TU_VERIFY(p_midi && info); + + info->daddr = p_midi->daddr; + + // re-construct descriptor + tusb_desc_interface_t* desc = &info->desc; + desc->bLength = sizeof(tusb_desc_interface_t); + desc->bDescriptorType = TUSB_DESC_INTERFACE; + + desc->bInterfaceNumber = p_midi->bInterfaceNumber; + desc->bAlternateSetting = 0; + desc->bNumEndpoints = (p_midi->ep_in != 0 ? 1:0) + (p_midi->ep_out != 0 ? 1:0); + desc->bInterfaceClass = TUSB_CLASS_AUDIO; + desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING; + desc->bInterfaceProtocol = 0; + desc->iInterface = 0; + + return true; +} + uint8_t tuh_midi_get_tx_cable_count (uint8_t idx) { TU_VERIFY(idx < CFG_TUH_MIDI); midih_interface_t *p_midi = &_midi_host[idx]; diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index b06bb43d7..67df25a82 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -90,6 +90,10 @@ bool tuh_midi_mounted(uint8_t idx); // return TUSB_INDEX_INVALID_8 (0xFF) if not found uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num); +// Get Interface information +// return true if index is correct and interface is currently mounted +bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info); + // return the number of virtual midi cables on the device's IN endpoint uint8_t tuh_midi_get_rx_cable_count(uint8_t idx); From 5ecea4eefe13ea93095da710dfcf3b3fee578c8e Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Tue, 18 Mar 2025 07:41:49 -0700 Subject: [PATCH 072/382] fix tuh_midi_itf_get_info() desc->iInterface value --- src/class/midi/midi_host.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 9019d476b..d6d204b7b 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -82,6 +82,7 @@ typedef struct { } ep_stream; bool mounted; + uint8_t iInterface; // for tuh_midi_itf_get_info() }midih_interface_t; typedef struct { @@ -228,6 +229,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); p_midi->bInterfaceNumber = desc_itf->bInterfaceNumber; + p_midi->iInterface = desc_itf->iInterface; p_midi->itf_count++; desc_cb.desc_midi = desc_itf; @@ -346,8 +348,7 @@ uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num) { return TUSB_INDEX_INVALID_8; } -bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) -{ +bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { midih_interface_t* p_midi = &_midi_host[idx]; TU_VERIFY(p_midi && info); @@ -364,7 +365,7 @@ bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) desc->bInterfaceClass = TUSB_CLASS_AUDIO; desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING; desc->bInterfaceProtocol = 0; - desc->iInterface = 0; + desc->iInterface = p_midi->iInterface; return true; } From 62f00bdf5d8b2a5941aed3d96865bbe24b117455 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Tue, 18 Mar 2025 07:42:47 -0700 Subject: [PATCH 073/382] Fix compiler conversion error warning --- src/class/midi/midi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index d6d204b7b..85253f5ca 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -361,7 +361,7 @@ bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { desc->bInterfaceNumber = p_midi->bInterfaceNumber; desc->bAlternateSetting = 0; - desc->bNumEndpoints = (p_midi->ep_in != 0 ? 1:0) + (p_midi->ep_out != 0 ? 1:0); + desc->bNumEndpoints = (uint8_t)((p_midi->ep_in != 0 ? 1:0) + (p_midi->ep_out != 0 ? 1:0)); desc->bInterfaceClass = TUSB_CLASS_AUDIO; desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING; desc->bInterfaceProtocol = 0; From 05e4f8b77786a6bbc4a43e3b8574689714ca3138 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Wed, 19 Mar 2025 05:57:01 -0700 Subject: [PATCH 074/382] Move iInterface per review comment --- src/class/midi/midi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 85253f5ca..cfea0c080 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -56,6 +56,7 @@ TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) i typedef struct { uint8_t daddr; uint8_t bInterfaceNumber; // interface number of MIDI streaming + uint8_t iInterface; uint8_t itf_count; // number of interface including Audio Control + MIDI streaming uint8_t ep_in; // IN endpoint address @@ -82,7 +83,6 @@ typedef struct { } ep_stream; bool mounted; - uint8_t iInterface; // for tuh_midi_itf_get_info() }midih_interface_t; typedef struct { From 4b46493cb4f8699c95e01783eee5cf90ca7810e2 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Thu, 20 Mar 2025 06:27:23 -0700 Subject: [PATCH 075/382] Fix #3033: Increase array bounds and test for overflow --- src/class/midi/midi_host.c | 3 ++- src/class/midi/midi_host.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index cfea0c080..68e46aca3 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -254,7 +254,8 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_LOG_DRV(" Jack %s %s descriptor \r\n", tu_desc_subtype(p_desc) == MIDI_CS_INTERFACE_IN_JACK ? "IN" : "OUT", p_desc[3] == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); - desc_cb.desc_jack[desc_cb.jack_num++] = p_desc; + if (desc_cb.jack_num < TU_ARRAY_SIZE(desc_cb.desc_jack)) + desc_cb.desc_jack[desc_cb.jack_num++] = p_desc; break; } diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index 67df25a82..06554a03d 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -69,7 +69,7 @@ typedef struct { const tusb_desc_endpoint_t* desc_epout; // endpoint OUT descriptor, CS_ENDPOINT is right after uint8_t jack_num; - const uint8_t* desc_jack[16]; // list of jack descriptors (embedded + external) + const uint8_t* desc_jack[32]; // list of jack descriptors (embedded + external) } tuh_midi_descriptor_cb_t; typedef struct { From e54753814befa26742fa8a9805f5b7beac32a963 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 21 Mar 2025 00:11:18 +0700 Subject: [PATCH 076/382] enable hil dual for metro m4 with max3421 --- examples/host/device_info/src/main.c | 2 +- src/host/usbh.h | 9 +++------ test/hil/tinyusb.json | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c index 775968c16..ac4c46a11 100644 --- a/examples/host/device_info/src/main.c +++ b/examples/host/device_info/src/main.c @@ -81,7 +81,7 @@ void init_freertos_task(void); //-------------------------------------------------------------------- // Main //-------------------------------------------------------------------- -void init_tinyusb(void) { +static void init_tinyusb(void) { // init host stack on configured roothub port tusb_rhport_init_t host_init = { .role = TUSB_ROLE_HOST, diff --git a/src/host/usbh.h b/src/host/usbh.h index 52b4f478c..36bb7c9b2 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -155,8 +155,7 @@ bool tuh_inited(void); void tuh_task_ext(uint32_t timeout_ms, bool in_isr); // Task function should be called in main/rtos loop -TU_ATTR_ALWAYS_INLINE static inline -void tuh_task(void) { +TU_ATTR_ALWAYS_INLINE static inline void tuh_task(void) { tuh_task_ext(UINT32_MAX, false); } @@ -197,16 +196,14 @@ bool tuh_mounted(uint8_t daddr); bool tuh_connected(uint8_t daddr); // Check if device is suspended -TU_ATTR_ALWAYS_INLINE static inline -bool tuh_suspended(uint8_t daddr) { +TU_ATTR_ALWAYS_INLINE static inline bool tuh_suspended(uint8_t daddr) { // TODO implement suspend & resume on host (void) daddr; return false; } // Check if device is ready to communicate with -TU_ATTR_ALWAYS_INLINE static inline -bool tuh_ready(uint8_t daddr) { +TU_ATTR_ALWAYS_INLINE static inline bool tuh_ready(uint8_t daddr) { return tuh_mounted(daddr) && !tuh_suspended(daddr); } diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index 7393226eb..c2bbdf5a3 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -60,7 +60,7 @@ "name": "metro_m4_express", "uid": "9995AD485337433231202020FF100A34", "tests": { - "device": true, "host": false, "dual": false, + "device": true, "host": false, "dual": true, "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2002130"}] }, "flasher": { From b0def52f45439c3dc41a0c370115deb54cd443e4 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Fri, 21 Mar 2025 07:13:01 -0700 Subject: [PATCH 077/382] Move misplaced statement --- src/class/midi/midi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 68e46aca3..b252e8466 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -591,8 +591,8 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff break; default: break; - cable_sysex_in_progress &= (uint16_t) ~cable_mask; } + cable_sysex_in_progress &= (uint16_t) ~cable_mask; } else { // Real-time message: can be inserted into a sysex message, // so do don't clear cable_sysex_in_progress bit From 3324a327cbd82d18305030ba2247cbbc71dc9f19 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Fri, 21 Mar 2025 07:14:10 -0700 Subject: [PATCH 078/382] Fix #3033: address review comment --- src/class/midi/midi_host.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index b252e8466..cd6e115ee 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -254,8 +254,9 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_LOG_DRV(" Jack %s %s descriptor \r\n", tu_desc_subtype(p_desc) == MIDI_CS_INTERFACE_IN_JACK ? "IN" : "OUT", p_desc[3] == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); - if (desc_cb.jack_num < TU_ARRAY_SIZE(desc_cb.desc_jack)) + if (desc_cb.jack_num < TU_ARRAY_SIZE(desc_cb.desc_jack)) { desc_cb.desc_jack[desc_cb.jack_num++] = p_desc; + } break; } From 9f541a3d961e1a75a9c6441cb3564c726292731b Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 24 Mar 2025 22:55:04 +0700 Subject: [PATCH 079/382] host: add tuh_enum_descriptor_device_cb() and tuh_enum_descriptor_configuration_cb() callback host: support device with multiple configurations --- src/host/usbh.c | 75 ++++++++++++++++++++++++++++--------------------- src/host/usbh.h | 7 +++-- 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index c87f058cd..308916c9b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -52,21 +52,25 @@ enum { // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ TU_ATTR_WEAK bool hcd_deinit(uint8_t rhport) { - (void) rhport; - return false; + (void) rhport; return false; } TU_ATTR_WEAK bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { - (void) rhport; - (void) cfg_id; - (void) cfg_param; + (void) rhport; (void) cfg_id; (void) cfg_param; return false; } +TU_ATTR_WEAK void tuh_enum_descriptor_device_cb(uint8_t daddr, const tusb_desc_device_t *desc_device) { + (void) daddr; (void) desc_device; +} + +TU_ATTR_WEAK bool tuh_enum_descriptor_configuration_cb(uint8_t daddr, uint8_t cfg_index, const tusb_desc_configuration_t *desc_config) { + (void) daddr; (void) cfg_index; (void) desc_config; + return true; +} + TU_ATTR_WEAK void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) { - (void) rhport; - (void) eventid; - (void) in_isr; + (void) rhport; (void) eventid; (void) in_isr; } TU_ATTR_WEAK bool hcd_dcache_clean(const void* addr, uint32_t data_size) { @@ -126,6 +130,7 @@ typedef struct { uint8_t i_manufacturer; uint8_t i_product; uint8_t i_serial; + uint8_t bNumConfigurations; // Configuration Descriptor // uint8_t interface_count; // bNumInterfaces alias @@ -230,7 +235,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = { }; enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; -enum { CONFIG_NUM = 1 }; // default to use configuration 1 // Additional class drivers implemented by application tu_static usbh_class_driver_t const * _app_driver = NULL; @@ -1372,8 +1376,8 @@ enum { ENUM_CONFIG_DRIVER }; -static bool enum_request_set_addr(void); -static bool _parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); +static bool enum_request_set_addr(tusb_desc_device_t const* desc_device); +static bool enum_parse_configuration_desc (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); static void enum_full_complete(void); // process device enumeration @@ -1489,7 +1493,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { #endif case ENUM_SET_ADDR: - enum_request_set_addr(); + enum_request_set_addr((tusb_desc_device_t*) _usbh_epbuf.ctrl); break; case ENUM_GET_DEVICE_DESC: { @@ -1523,6 +1527,9 @@ static void process_enumeration(tuh_xfer_t* xfer) { dev->i_manufacturer = desc_device->iManufacturer; dev->i_product = desc_device->iProduct; dev->i_serial = desc_device->iSerialNumber; + dev->bNumConfigurations = desc_device->bNumConfigurations; + + tuh_enum_descriptor_device_cb(daddr, desc_device); // callback tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE, process_enumeration, ENUM_GET_STRING_MANUFACTURER); @@ -1574,8 +1581,8 @@ static void process_enumeration(tuh_xfer_t* xfer) { case ENUM_GET_9BYTE_CONFIG_DESC: { // Get 9-byte for total length - uint8_t const config_idx = CONFIG_NUM - 1; - TU_LOG_USBH("Get Configuration[0] Descriptor (9 bytes)\r\n"); + uint8_t const config_idx = 0; + TU_LOG_USBH("Get Configuration[%u] Descriptor (9 bytes)\r\n", config_idx); TU_ASSERT(tuh_descriptor_get_configuration(daddr, config_idx, _usbh_epbuf.ctrl, 9, process_enumeration, ENUM_GET_FULL_CONFIG_DESC),); break; @@ -1585,25 +1592,32 @@ static void process_enumeration(tuh_xfer_t* xfer) { uint8_t const* desc_config = _usbh_epbuf.ctrl; // Use offsetof to avoid pointer to the odd/misaligned address - uint16_t const total_len = tu_le16toh( - tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength))); + uint16_t const total_len = tu_le16toh(tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength))); // TODO not enough buffer to hold configuration descriptor TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE,); // Get full configuration descriptor - uint8_t const config_idx = CONFIG_NUM - 1; - TU_LOG_USBH("Get Configuration[0] Descriptor\r\n"); + uint8_t const config_idx = (uint8_t) tu_le16toh(xfer->setup->wIndex); + TU_LOG_USBH("Get Configuration[%u] Descriptor\r\n", config_idx); TU_ASSERT(tuh_descriptor_get_configuration(daddr, config_idx, _usbh_epbuf.ctrl, total_len, process_enumeration, ENUM_SET_CONFIG),); break; } - case ENUM_SET_CONFIG: - // tuh_desc_configuration_cb(daddr, CONFIG_NUM-1, (const tusb_desc_configuration_t*) _usbh_epbuf.ctrl); - - TU_ASSERT(tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER),); + case ENUM_SET_CONFIG: { + uint8_t config_idx = (uint8_t) tu_le16toh(xfer->setup->wIndex); + if (tuh_enum_descriptor_configuration_cb(daddr, config_idx, (const tusb_desc_configuration_t*) _usbh_epbuf.ctrl)) { + TU_ASSERT(tuh_configuration_set(daddr, config_idx+1, process_enumeration, ENUM_CONFIG_DRIVER),); + } else { + config_idx++; + TU_ASSERT(config_idx < dev->bNumConfigurations,); + TU_LOG_USBH("Get Configuration[%u] Descriptor (9 bytes)\r\n", config_idx); + TU_ASSERT(tuh_descriptor_get_configuration(daddr, config_idx, _usbh_epbuf.ctrl, 9, + process_enumeration, ENUM_GET_FULL_CONFIG_DESC),); + } break; + } case ENUM_CONFIG_DRIVER: { TU_LOG_USBH("Device configured\r\n"); @@ -1613,7 +1627,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { // Parse configuration & set up drivers // driver_open() must not make any usb transfer - TU_ASSERT(_parse_configuration_descriptor(daddr, (tusb_desc_configuration_t*) _usbh_epbuf.ctrl),); + TU_ASSERT(enum_parse_configuration_desc(daddr, (tusb_desc_configuration_t*) _usbh_epbuf.ctrl),); // Start the Set Configuration process for interfaces (itf = TUSB_INDEX_INVALID_8) // Since driver can perform control transfer within its set_config, this is done asynchronously. @@ -1624,14 +1638,11 @@ static void process_enumeration(tuh_xfer_t* xfer) { } default: - // stop enumeration if unknown state - enum_full_complete(); + enum_full_complete(); // stop enumeration if unknown state break; } } - - static bool enum_new_device(hcd_event_t* event) { _dev0.rhport = event->rhport; _dev0.hub_addr = event->connection.hub_addr; @@ -1701,9 +1712,7 @@ static uint8_t get_new_address(bool is_hub) { return 0; // invalid address } -static bool enum_request_set_addr(void) { - tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl; - +static bool enum_request_set_addr(tusb_desc_device_t const* desc_device) { // Get new address uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); TU_ASSERT(new_addr != 0); @@ -1741,7 +1750,7 @@ static bool enum_request_set_addr(void) { return true; } -static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { +static bool enum_parse_configuration_desc(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { usbh_device_t* dev = get_device(dev_addr); uint16_t const total_len = tu_le16toh(desc_cfg->wTotalLength); uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + total_len; @@ -1858,7 +1867,9 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { TU_LOG_USBH("HUB address = %u is mounted\r\n", dev_addr); }else { // Invoke callback if available - if (tuh_mount_cb) tuh_mount_cb(dev_addr); + if (tuh_mount_cb) { + tuh_mount_cb(dev_addr); + } } } } diff --git a/src/host/usbh.h b/src/host/usbh.h index 36bb7c9b2..d95bb9b57 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -100,10 +100,13 @@ typedef union { //--------------------------------------------------------------------+ // Invoked when enumeration get device descriptor -// TU_ATTR_WEAK void tuh_descriptor_device_cb(uint8_t daddr, const tusb_desc_device_t *desc_device); +// Device is not ready to communicate yet, application can copy the descriptor if needed +void tuh_enum_descriptor_device_cb(uint8_t daddr, const tusb_desc_device_t *desc_device); // Invoked when enumeration get configuration descriptor -// TU_ATTR_WEAK void tuh_desc_configuration_cb(uint8_t daddr, uint8_t cfg_index, const tusb_desc_configuration_t *desc_config); +// For multi-configuration device return false to skip, true to proceed with this configuration (may not be implemented yet) +// Device is not ready to communicate yet, application can copy the descriptor if needed +bool tuh_enum_descriptor_configuration_cb(uint8_t daddr, uint8_t cfg_index, const tusb_desc_configuration_t *desc_config); // Invoked when a device is mounted (configured) TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr); From db537861b2e39debe09009762a968edfcd4a9618 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 24 Mar 2025 22:58:21 +0700 Subject: [PATCH 080/382] device cdc: rename tud_cdc_configure_fifo/_t to tud_cdc_configure/_t add tx_overwritabe_if_not_connected for cdc driver configure --- src/class/cdc/cdc_device.c | 38 ++++++++++++++++++++------------------ src/class/cdc/cdc_device.h | 22 ++++++++++++++++------ src/common/tusb_fifo.c | 7 +++++-- 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index efb672201..4d19adeb4 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -82,7 +82,7 @@ typedef struct { static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC]; -static tud_cdc_configure_fifo_t _cdcd_fifo_cfg; +static tud_cdc_configure_t _cdcd_cfg = TUD_CDC_CONFIGURE_DEFAULT(); static bool _prep_out_transaction(uint8_t itf) { const uint8_t rhport = 0; @@ -119,9 +119,9 @@ static bool _prep_out_transaction(uint8_t itf) { // APPLICATION API //--------------------------------------------------------------------+ -bool tud_cdc_configure_fifo(const tud_cdc_configure_fifo_t* cfg) { - TU_VERIFY(cfg); - _cdcd_fifo_cfg = (*cfg); +bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg) { + TU_VERIFY(driver_cfg); + _cdcd_cfg = *driver_cfg; return true; } @@ -175,7 +175,7 @@ void tud_cdc_n_read_flush(uint8_t itf) { //--------------------------------------------------------------------+ uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); + uint16_t wr_count = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); // flush if queue more than packet size if (tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE @@ -186,7 +186,7 @@ uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) { tud_cdc_n_write_flush(itf); } - return ret; + return wr_count; } uint32_t tud_cdc_n_write_flush(uint8_t itf) { @@ -233,8 +233,6 @@ bool tud_cdc_n_write_clear(uint8_t itf) { //--------------------------------------------------------------------+ void cdcd_init(void) { tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); - tu_memclr(&_cdcd_fifo_cfg, sizeof(_cdcd_fifo_cfg)); - for (uint8_t i = 0; i < CFG_TUD_CDC; i++) { cdcd_interface_t* p_cdc = &_cdcd_itf[i]; @@ -249,10 +247,10 @@ void cdcd_init(void) { // Config RX fifo tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); - // Config TX fifo as overwritable at initialization and will be changed to non-overwritable - // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal. - // In this way, the most current data is prioritized. - tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true); + // TX fifo can be configured to change to overwritable if not connected (DTR bit not set). Without DTR we do not + // know if data is actually polled by terminal. This way the most current data is prioritized. + // Default: is overwritable + tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, _cdcd_cfg.tx_overwritabe_if_not_connected); #if OSAL_MUTEX_REQUIRED osal_mutex_t mutex_rd = osal_mutex_create(&p_cdc->rx_ff_mutex); @@ -294,13 +292,13 @@ void cdcd_reset(uint8_t rhport) { cdcd_interface_t* p_cdc = &_cdcd_itf[i]; tu_memclr(p_cdc, ITF_MEM_RESET_SIZE); - if (!_cdcd_fifo_cfg.rx_persistent) { + if (!_cdcd_cfg.rx_persistent) { tu_fifo_clear(&p_cdc->rx_ff); } - if (!_cdcd_fifo_cfg.tx_persistent) { + if (!_cdcd_cfg.tx_persistent) { tu_fifo_clear(&p_cdc->tx_ff); } - tu_fifo_set_overwritable(&p_cdc->tx_ff, true); + tu_fifo_set_overwritable(&p_cdc->tx_ff, _cdcd_cfg.tx_overwritabe_if_not_connected); } } @@ -414,8 +412,12 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ p_cdc->line_state = (uint8_t) request->wValue; - // Disable fifo overwriting if DTR bit is set - tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); + // If enabled: fifo overwriting is disabled if DTR bit is set and vice versa + if (_cdcd_cfg.tx_overwritabe_if_not_connected) { + tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); + } else { + tu_fifo_set_overwritable(&p_cdc->tx_ff, false); + } TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); @@ -496,7 +498,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // xferred_bytes is multiple of EP Packet size and not zero if (!tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE - 1)))) { if (usbd_edpt_claim(rhport, p_cdc->ep_in)) { - usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0); + TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0)); } } } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 2d5ba2575..b653ebd74 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -48,14 +48,24 @@ //--------------------------------------------------------------------+ // Driver Configuration //--------------------------------------------------------------------+ - typedef struct TU_ATTR_PACKED { - uint8_t rx_persistent : 1; // keep rx fifo on bus reset or disconnect - uint8_t tx_persistent : 1; // keep tx fifo on bus reset or disconnect -} tud_cdc_configure_fifo_t; + uint8_t rx_persistent : 1; // keep rx fifo data even with bus reset or disconnect + uint8_t tx_persistent : 1; // keep tx fifo data even with reset or disconnect + uint8_t tx_overwritabe_if_not_connected : 1; // if not connected, tx fifo can be overwritten +} tud_cdc_configure_t; -// Configure CDC FIFOs behavior -bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg); +#define TUD_CDC_CONFIGURE_DEFAULT() { \ + .rx_persistent = 0, \ + .tx_persistent = 0, \ + .tx_overwritabe_if_not_connected = 1, \ +} + +// Configure CDC driver behavior +bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg); + +// Backward compatible +#define tud_cdc_configure_fifo_t tud_cdc_configure_t +#define tud_cdc_configure_fifo tud_cdc_configure //--------------------------------------------------------------------+ // Application API (Multiple Ports) i.e. CFG_TUD_CDC > 1 diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 5f2dcabad..ecf002b09 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -916,8 +916,11 @@ bool tu_fifo_clear(tu_fifo_t *f) Overwritable mode the fifo is set to */ /******************************************************************************/ -bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) -{ +bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { + if (f->overwritable == overwritable) { + return true; + } + _ff_lock(f->mutex_wr); _ff_lock(f->mutex_rd); From 875e645b324082a00072a45ae64a8fcdace7303a Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 24 Mar 2025 23:20:54 +0700 Subject: [PATCH 081/382] update hil test to include dual and host for pico/pico2 --- .../dual/host_info_to_device_cdc/src/main.c | 163 +++++++++--------- test/hil/hil_test.py | 22 ++- test/hil/tinyusb.json | 4 +- 3 files changed, 100 insertions(+), 89 deletions(-) diff --git a/examples/dual/host_info_to_device_cdc/src/main.c b/examples/dual/host_info_to_device_cdc/src/main.c index 668808db2..c1017141c 100644 --- a/examples/dual/host_info_to_device_cdc/src/main.c +++ b/examples/dual/host_info_to_device_cdc/src/main.c @@ -70,8 +70,11 @@ enum { static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; static bool is_print[CFG_TUH_DEVICE_MAX+1] = { 0 }; +static tusb_desc_device_t descriptor_device[CFG_TUH_DEVICE_MAX+1]; static void print_utf16(uint16_t *temp_buf, size_t buf_len); +static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_device); + void led_blinking_task(void); void cdc_task(void); @@ -135,84 +138,19 @@ void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } -#if 1 -#define cdc_printf(...) \ - do { \ - char _tempbuf[256]; \ - int count = sprintf(_tempbuf, __VA_ARGS__); \ - tud_cdc_write(_tempbuf, (uint32_t) count); \ - tud_cdc_write_flush(); \ - tud_task(); \ - } while(0) -#endif - -//#define cdc_printf printf - -void print_device_info(uint8_t daddr) { - tusb_desc_device_t desc_device; - uint8_t xfer_result = tuh_descriptor_get_device_sync(daddr, &desc_device, 18); - if (XFER_RESULT_SUCCESS != xfer_result) { - tud_cdc_write_str("Failed to get device descriptor\r\n"); +void cdc_task(void) { + if (!tud_cdc_connected()) { + // delay a bit otherwise we can outpace host's terminal. Linux will set LineState (DTR) then Line Coding. + // If we send data before Linux's terminal set Line Coding, it can be ignored --> missing data with hardware test loop + board_delay(10); return; } - // Get String descriptor using Sync API - uint16_t serial[64]; - uint16_t buf[128]; - - cdc_printf("Device %u: ID %04x:%04x SN ", daddr, desc_device.idVendor, desc_device.idProduct); - xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, serial, sizeof(serial)); - if (XFER_RESULT_SUCCESS != xfer_result) { - serial[0] = 'n'; - serial[1] = '/'; - serial[2] = 'a'; - serial[3] = 0; - } - print_utf16(serial, TU_ARRAY_SIZE(serial)); - tud_cdc_write_str("\r\n"); - - cdc_printf("Device Descriptor:\r\n"); - cdc_printf(" bLength %u\r\n" , desc_device.bLength); - cdc_printf(" bDescriptorType %u\r\n" , desc_device.bDescriptorType); - cdc_printf(" bcdUSB %04x\r\n" , desc_device.bcdUSB); - cdc_printf(" bDeviceClass %u\r\n" , desc_device.bDeviceClass); - cdc_printf(" bDeviceSubClass %u\r\n" , desc_device.bDeviceSubClass); - cdc_printf(" bDeviceProtocol %u\r\n" , desc_device.bDeviceProtocol); - cdc_printf(" bMaxPacketSize0 %u\r\n" , desc_device.bMaxPacketSize0); - cdc_printf(" idVendor 0x%04x\r\n" , desc_device.idVendor); - cdc_printf(" idProduct 0x%04x\r\n" , desc_device.idProduct); - cdc_printf(" bcdDevice %04x\r\n" , desc_device.bcdDevice); - - cdc_printf(" iManufacturer %u " , desc_device.iManufacturer); - xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf)); - if (XFER_RESULT_SUCCESS == xfer_result ) { - print_utf16(buf, TU_ARRAY_SIZE(buf)); - } - tud_cdc_write_str("\r\n"); - - cdc_printf(" iProduct %u " , desc_device.iProduct); - xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf)); - if (XFER_RESULT_SUCCESS == xfer_result) { - print_utf16(buf, TU_ARRAY_SIZE(buf)); - } - tud_cdc_write_str("\r\n"); - - cdc_printf(" iSerialNumber %u " , desc_device.iSerialNumber); - tud_cdc_write_str((char*)serial); // serial is already to UTF-8 - tud_cdc_write_str("\r\n"); - - cdc_printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations); -} - -void cdc_task(void) { - if (tud_cdc_connected()) { - for (uint8_t daddr = 1; daddr <= CFG_TUH_DEVICE_MAX; daddr++) { - if (tuh_mounted(daddr)) { - if (is_print[daddr]) { - is_print[daddr] = false; - print_device_info(daddr); - tud_cdc_write_flush(); - } + for (uint8_t daddr = 1; daddr <= CFG_TUH_DEVICE_MAX; daddr++) { + if (tuh_mounted(daddr)) { + if (is_print[daddr]) { + is_print[daddr] = false; + print_device_info(daddr, &descriptor_device[daddr]); } } } @@ -221,6 +159,77 @@ void cdc_task(void) { //--------------------------------------------------------------------+ // Host Get device information //--------------------------------------------------------------------+ +#define cdc_printf(...) \ + do { \ + char _tempbuf[256]; \ + char* _bufptr = _tempbuf; \ + uint32_t count = (uint32_t) sprintf(_tempbuf, __VA_ARGS__); \ + while (count > 0) { \ + uint32_t wr_count = tud_cdc_write(_bufptr, count); \ + count -= wr_count; \ + _bufptr += wr_count; \ + if (count > 0){ \ + tud_task();\ + tud_cdc_write_flush(); \ + } \ + } \ + } while(0) + +static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_device) { + // Get String descriptor using Sync API + uint16_t serial[64]; + uint16_t buf[128]; + (void) buf; + + cdc_printf("Device %u: ID %04x:%04x SN ", daddr, desc_device->idVendor, desc_device->idProduct); + uint8_t xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, serial, sizeof(serial)); + if (XFER_RESULT_SUCCESS != xfer_result) { + serial[0] = 'n'; + serial[1] = '/'; + serial[2] = 'a'; + serial[3] = 0; + } + print_utf16(serial, TU_ARRAY_SIZE(serial)); + cdc_printf("\r\n"); + + cdc_printf("Device Descriptor:\r\n"); + cdc_printf(" bLength %u\r\n" , desc_device->bLength); + cdc_printf(" bDescriptorType %u\r\n" , desc_device->bDescriptorType); + cdc_printf(" bcdUSB %04x\r\n" , desc_device->bcdUSB); + cdc_printf(" bDeviceClass %u\r\n" , desc_device->bDeviceClass); + cdc_printf(" bDeviceSubClass %u\r\n" , desc_device->bDeviceSubClass); + cdc_printf(" bDeviceProtocol %u\r\n" , desc_device->bDeviceProtocol); + cdc_printf(" bMaxPacketSize0 %u\r\n" , desc_device->bMaxPacketSize0); + cdc_printf(" idVendor 0x%04x\r\n" , desc_device->idVendor); + cdc_printf(" idProduct 0x%04x\r\n" , desc_device->idProduct); + cdc_printf(" bcdDevice %04x\r\n" , desc_device->bcdDevice); + + cdc_printf(" iManufacturer %u " , desc_device->iManufacturer); + xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf)); + if (XFER_RESULT_SUCCESS == xfer_result) { + print_utf16(buf, TU_ARRAY_SIZE(buf)); + } + cdc_printf("\r\n"); + + cdc_printf(" iProduct %u " , desc_device->iProduct); + xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf)); + if (XFER_RESULT_SUCCESS == xfer_result) { + print_utf16(buf, TU_ARRAY_SIZE(buf)); + } + cdc_printf("\r\n"); + + cdc_printf(" iSerialNumber %u " , desc_device->iSerialNumber); + cdc_printf((char*)serial); // serial is already to UTF-8 + cdc_printf("\r\n"); + + cdc_printf(" bNumConfigurations %u\r\n" , desc_device->bNumConfigurations); +} + +void tuh_enum_descriptor_device_cb(uint8_t daddr, tusb_desc_device_t const* desc_device) { + (void) daddr; + descriptor_device[daddr] = *desc_device; // save device descriptor +} + void tuh_mount_cb(uint8_t daddr) { printf("mounted device %u\r\n", daddr); is_print[daddr] = true; @@ -296,7 +305,5 @@ static void print_utf16(uint16_t *temp_buf, size_t buf_len) { _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); ((uint8_t*) temp_buf)[utf8_len] = '\0'; - tud_cdc_write(temp_buf, utf8_len); - tud_cdc_write_flush(); - tud_task(); + cdc_printf((char*) temp_buf); } diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index a9f5dc1e1..11b67082c 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -81,7 +81,7 @@ def get_serial_dev(id, vendor_str, product_str, ifnum): return f'/dev/serial/by-id/usb-{vendor_str}_{product_str}_{id}-if{ifnum:02d}' else: # just use id: mostly for cp210x/ftdi flasher - pattern = f'/dev/serial/by-id/usb-*_{id}-if{ifnum:02d}*' + pattern = f'/dev/serial/by-id/usb-*_{id}-if*' port_list = glob.glob(pattern) return port_list[0] @@ -98,18 +98,19 @@ def get_hid_dev(id, vendor_str, product_str, event): def open_serial_dev(port): timeout = ENUM_TIMEOUT ser = None + t_step = 0.1 while timeout: if os.path.exists(port): try: # slight delay since kernel may occupy the port briefly - time.sleep(0.5) - timeout = timeout - 0.5 + time.sleep(t_step) + timeout = timeout - t_step ser = serial.Serial(port, baudrate=115200, timeout=5) break except serial.SerialException: pass - time.sleep(0.5) - timeout = timeout - 0.5 + time.sleep(t_step) + timeout = timeout - t_step assert timeout, f'Cannot open port f{port}' if os.path.exists(port) else f'Port {port} not existed' return ser @@ -202,14 +203,14 @@ def reset_stflash(board): def flash_openocd(board, firmware): flasher = board['flasher'] ret = run_cmd(f'openocd -c "tcl_port disabled" -c "gdb_port disabled" -c "adapter serial {flasher["uid"]}" ' - f'{flasher["args"]} -c init -c halt -c "program {firmware}.elf verify" -c reset -c exit') + f'{flasher["args"]} -c "init; halt; program {firmware}.elf verify; reset; exit"') return ret def reset_openocd(board): flasher = board['flasher'] ret = run_cmd(f'openocd -c "tcl_port disabled" -c "gdb_port disabled" -c "adapter serial {flasher["uid"]}" ' - f'{flasher["args"]} -c "reset exit"') + f'{flasher["args"]} -c "init; reset run; exit"') return ret @@ -310,6 +311,9 @@ def test_dual_host_info_to_device_cdc(board): assert False, 'No data from device' lines = data.decode('utf-8').splitlines() + if verbose: + print('\n'.join(lines)) + enum_dev_sn = [] for l in lines: vid_pid_sn = re.search(r'ID ([0-9a-fA-F]+):([0-9a-fA-F]+) SN (\w+)', l) @@ -577,10 +581,10 @@ def test_board(board): print(f' {e}') else: print() - print(f' Test failed: {e}, retry {i+1}') + print(f' Test failed: {e}, retry {i+2}/{max_rety}') time.sleep(1) else: - print(f'Flashing failed, retry {i+1}') + print(f'Flashing failed, retry {i+2}/{max_rety}') time.sleep(1) if ret.returncode != 0: diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index c2bbdf5a3..e702ffe9f 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -99,7 +99,7 @@ "name": "raspberry_pi_pico", "uid": "E6614C311B764A37", "tests": { - "device": true, "host": false, "dual": false, + "device": true, "host": true, "dual": true, "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2002470"}] }, "flasher": { @@ -112,7 +112,7 @@ "name": "raspberry_pi_pico2", "uid": "560AE75E1C7152C9", "tests": { - "device": true, "host": false, "dual": false, + "device": true, "host": true, "dual": true, "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "533D004242"}] }, "flasher": { From c3a6efc29ef49752a771b8d5615730370b37580e Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 24 Mar 2025 23:06:09 +0100 Subject: [PATCH 082/382] Implement ITM_SendChar(). Signed-off-by: HiFiPhile --- hw/bsp/board.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 0e0fa4ac6..4b8e5950f 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -64,13 +64,27 @@ int sys_read(int fhdl, char *buf, size_t count) { #endif #elif defined(LOGGER_SWO) + +#define ITM_BASE 0xE0000000 + +#define ITM_STIM0 (*((volatile uint8_t*)(ITM_BASE + 0))) +#define ITM_TER *((volatile uint32_t*)(ITM_BASE + 0xE00)) +#define ITM_TCR *((volatile uint32_t*)(ITM_BASE + 0xE80)) + +#define ITM_TCR_ITMENA (1 << 0) + // Logging with SWO for ARM Cortex-M int sys_write (int fhdl, const char *buf, size_t count) { (void) fhdl; uint8_t const* buf8 = (uint8_t const*) buf; - for(size_t i=0; i Date: Mon, 24 Mar 2025 23:06:22 +0100 Subject: [PATCH 083/382] Add SWO config. Signed-off-by: HiFiPhile --- hw/bsp/stm32h7rs/family.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/hw/bsp/stm32h7rs/family.c b/hw/bsp/stm32h7rs/family.c index 1fbbd3cdb..4b81deea0 100644 --- a/hw/bsp/stm32h7rs/family.c +++ b/hw/bsp/stm32h7rs/family.c @@ -63,6 +63,10 @@ UART_HandleTypeDef UartHandle = { }; #endif +#ifndef SWO_FREQ +#define SWO_FREQ 4000000 +#endif + //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ @@ -97,6 +101,28 @@ void trace_etm_init(void) { #define trace_etm_init() #endif +#ifdef LOGGER_SWO +void log_swo_init(void) +{ + //UNLOCK FUNNEL + *(volatile uint32_t*)(0x5C004FB0) = 0xC5ACCE55; // SWTF_LAR + *(volatile uint32_t*)(0x5C003FB0) = 0xC5ACCE55; // SWO_LAR + + //SWO current output divisor register + //To change it, you can use the following rule + // value = (CPU_Freq / 3 / SWO_Freq) - 1 + *(volatile uint32_t*)(0x5C003010) = ((SystemCoreClock / 3 / SWO_FREQ) - 1); // SWO_CODR + + //SWO selected pin protocol register + *(volatile uint32_t*)(0x5C0030F0) = 0x00000002; // SWO_SPPR + + //Enable ITM input of SWO trace funnel + *(volatile uint32_t*)(0x5C004000) |= 0x00000001; // SWFT_CTRL +} +#else + #define log_swo_init() +#endif + void board_init(void) { HAL_Init(); @@ -117,6 +143,7 @@ void board_init(void) { __HAL_RCC_GPIOO_CLK_ENABLE(); __HAL_RCC_GPIOP_CLK_ENABLE(); + log_swo_init(); trace_etm_init(); for (uint8_t i = 0; i < TU_ARRAY_SIZE(board_pindef); i++) { From 1fd5c123162519a21a09c0f8030e9fbbad63cd3b Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 25 Mar 2025 10:43:55 +0700 Subject: [PATCH 084/382] HIL: add flag CFG_TUH_RPI_PIO_USB to pico/pico2 --- test/hil/hil_test.py | 5 ++--- test/hil/tinyusb.json | 6 ++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 11b67082c..8b83731c4 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -311,9 +311,6 @@ def test_dual_host_info_to_device_cdc(board): assert False, 'No data from device' lines = data.decode('utf-8').splitlines() - if verbose: - print('\n'.join(lines)) - enum_dev_sn = [] for l in lines: vid_pid_sn = re.search(r'ID ([0-9a-fA-F]+):([0-9a-fA-F]+) SN (\w+)', l) @@ -323,6 +320,7 @@ def test_dual_host_info_to_device_cdc(board): if set(declared_devs) != set(enum_dev_sn): failed_msg = f'Expected {declared_devs}, Enumerated {enum_dev_sn}' + print('\n'.join(lines)) assert False, failed_msg return 0 @@ -356,6 +354,7 @@ def test_host_device_info(board): if set(declared_devs) != set(enum_dev_sn): failed_msg = f'Expected {declared_devs}, Enumerated {enum_dev_sn}' + print('\n'.join(lines)) assert False, failed_msg return 0 diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index e702ffe9f..fb4c05c3d 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -98,6 +98,9 @@ { "name": "raspberry_pi_pico", "uid": "E6614C311B764A37", + "build" : { + "flags_on": ["CFG_TUH_RPI_PIO_USB"] + }, "tests": { "device": true, "host": true, "dual": true, "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2002470"}] @@ -111,6 +114,9 @@ { "name": "raspberry_pi_pico2", "uid": "560AE75E1C7152C9", + "build" : { + "flags_on": ["CFG_TUH_RPI_PIO_USB"] + }, "tests": { "device": true, "host": true, "dual": true, "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "533D004242"}] From b99b811308114d07cbba0d432abc185c05896ec3 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 25 Mar 2025 14:43:40 +0700 Subject: [PATCH 085/382] more hil improvement --- test/hil/hil_test.py | 37 +++++++++++++++++-------------------- test/hil/tinyusb.json | 4 ++-- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 8b83731c4..017c17018 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -98,21 +98,18 @@ def get_hid_dev(id, vendor_str, product_str, event): def open_serial_dev(port): timeout = ENUM_TIMEOUT ser = None - t_step = 0.1 - while timeout: + while timeout > 0: if os.path.exists(port): try: - # slight delay since kernel may occupy the port briefly - time.sleep(t_step) - timeout = timeout - t_step ser = serial.Serial(port, baudrate=115200, timeout=5) break except serial.SerialException: + print(f'serial {port} not reaady {timeout} sec') pass - time.sleep(t_step) - timeout = timeout - t_step + time.sleep(0.1) + timeout -= 0.1 - assert timeout, f'Cannot open port f{port}' if os.path.exists(port) else f'Port {port} not existed' + assert timeout > 0, f'Cannot open port f{port}' if os.path.exists(port) else f'Port {port} not existed' return ser @@ -120,7 +117,7 @@ def read_disk_file(uid, lun, fname): # open_fs("fat://{dev}) require 'pip install pyfatfs' dev = get_disk_dev(uid, 'TinyUSB', lun) timeout = ENUM_TIMEOUT - while timeout: + while timeout > 0: if os.path.exists(dev): fat = fs.open_fs(f'fat://{dev}?read_only=true') try: @@ -133,7 +130,7 @@ def read_disk_file(uid, lun, fname): time.sleep(1) timeout -= 1 - assert timeout, f'Storage {dev} not existed' + assert timeout > 0, f'Storage {dev} not existed' return None @@ -305,11 +302,11 @@ def test_dual_host_info_to_device_cdc(board): ser = open_serial_dev(port) # read from cdc, first line should contain vid/pid and serial - data = ser.read(1000) + data = ser.read(10000) ser.close() if len(data) == 0: assert False, 'No data from device' - lines = data.decode('utf-8').splitlines() + lines = data.decode('utf-8', errors='ignore').splitlines() enum_dev_sn = [] for l in lines: @@ -339,12 +336,12 @@ def test_host_device_info(board): ret = globals()[f'reset_{flasher["name"].lower()}'](board) assert ret.returncode == 0, 'Failed to reset device' - data = ser.read(1000) + data = ser.read(10000) ser.close() if len(data) == 0: assert False, 'No data from device' - lines = data.decode('utf-8').splitlines() + lines = data.decode('utf-8', errors='ignore').splitlines() enum_dev_sn = [] for l in lines: vid_pid_sn = re.search(r'ID ([0-9a-fA-F]+):([0-9a-fA-F]+) SN (\w+)', l) @@ -422,7 +419,7 @@ def test_device_dfu(board): # Wait device enum timeout = ENUM_TIMEOUT - while timeout: + while timeout > 0: ret = run_cmd(f'dfu-util -l') stdout = ret.stdout.decode() if f'serial="{uid}"' in stdout and 'Found DFU: [cafe:4000]' in stdout: @@ -430,7 +427,7 @@ def test_device_dfu(board): time.sleep(1) timeout = timeout - 1 - assert timeout, 'Device not available' + assert timeout > 0, 'Device not available' f_dfu0 = f'dfu0_{uid}' f_dfu1 = f'dfu1_{uid}' @@ -463,7 +460,7 @@ def test_device_dfu_runtime(board): # Wait device enum timeout = ENUM_TIMEOUT - while timeout: + while timeout > 0: ret = run_cmd(f'dfu-util -l') stdout = ret.stdout.decode() if f'serial="{uid}"' in stdout and 'Found Runtime: [cafe:4000]' in stdout: @@ -471,7 +468,7 @@ def test_device_dfu_runtime(board): time.sleep(1) timeout = timeout - 1 - assert timeout, 'Device not available' + assert timeout > 0, 'Device not available' def test_device_hid_boot_interface(board): @@ -481,13 +478,13 @@ def test_device_hid_boot_interface(board): mouse2 = get_hid_dev(uid, 'TinyUSB', 'TinyUSB_Device', 'if01-mouse') # Wait device enum timeout = ENUM_TIMEOUT - while timeout: + while timeout > 0: if os.path.exists(kbd) and os.path.exists(mouse1) and os.path.exists(mouse2): break time.sleep(1) timeout = timeout - 1 - assert timeout, 'HID device not available' + assert timeout > 0, 'HID device not available' def test_device_hid_composite_freertos(id): diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index fb4c05c3d..7436ddb63 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -163,9 +163,9 @@ "device": true, "host": false, "dual": false }, "flasher": { - "name": "stlink", + "name": "openocd", "uid": "004C00343137510F39383538", - "args": "" + "args": "-f interface/stlink.cfg -f target/stm32h7x.cfg" } }, { From 65e01fff2e7ab5302baa45bdd81a1d774e269452 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 25 Mar 2025 16:15:58 +0700 Subject: [PATCH 086/382] add tuh_edpt_close() API, it will abort any pending transfer implement hcd_edpt_close() for pio-usb and max3421e, also move max3421e api into its own header. --- examples/host/bare_api/src/main.c | 244 ++++++++---------- src/host/hcd.h | 3 + src/host/usbh.c | 6 + src/host/usbh.h | 7 + src/portable/analog/max3421/hcd_max3421.c | 40 ++- src/portable/analog/max3421/hcd_max3421.h | 63 +++++ .../raspberrypi/pio_usb/hcd_pio_usb.c | 5 + tools/get_deps.py | 4 +- 8 files changed, 213 insertions(+), 159 deletions(-) create mode 100644 src/portable/analog/max3421/hcd_max3421.h diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index f582f4f5a..0c76ff0c9 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -55,16 +55,15 @@ uint8_t* get_hid_buf(uint8_t daddr); void free_hid_buf(uint8_t daddr); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); printf("TinyUSB Bare API Example\r\n"); // init host stack on configured roothub port tusb_rhport_init_t host_init = { - .role = TUSB_ROLE_HOST, - .speed = TUSB_SPEED_AUTO + .role = TUSB_ROLE_HOST, + .speed = TUSB_SPEED_AUTO }; tusb_init(BOARD_TUH_RHPORT, &host_init); @@ -72,8 +71,7 @@ int main(void) board_init_after_tusb(); } - while (1) - { + while (1) { // tinyusb host task tuh_task(); led_blinking_task(); @@ -85,8 +83,7 @@ int main(void) /*------------- TinyUSB Callbacks -------------*/ // Invoked when device is mounted (configured) -void tuh_mount_cb (uint8_t daddr) -{ +void tuh_mount_cb(uint8_t daddr) { printf("Device attached, address = %d\r\n", daddr); // Get Device Descriptor @@ -95,8 +92,7 @@ void tuh_mount_cb (uint8_t daddr) } /// Invoked when device is unmounted (bus reset/unplugged) -void tuh_umount_cb(uint8_t daddr) -{ +void tuh_umount_cb(uint8_t daddr) { printf("Device removed, address = %d\r\n", daddr); free_hid_buf(daddr); } @@ -104,11 +100,8 @@ void tuh_umount_cb(uint8_t daddr) //--------------------------------------------------------------------+ // Device Descriptor //--------------------------------------------------------------------+ - -void print_device_descriptor(tuh_xfer_t* xfer) -{ - if ( XFER_RESULT_SUCCESS != xfer->result ) - { +void print_device_descriptor(tuh_xfer_t *xfer) { + if (XFER_RESULT_SUCCESS != xfer->result) { printf("Failed to get device descriptor\r\n"); return; } @@ -131,33 +124,29 @@ void print_device_descriptor(tuh_xfer_t* xfer) // Get String descriptor using Sync API uint16_t temp_buf[128]; - printf(" iManufacturer %u " , desc_device.iManufacturer); - if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf)) ) - { + printf(" iManufacturer %u ", desc_device.iManufacturer); + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) { print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf)); } printf("\r\n"); - printf(" iProduct %u " , desc_device.iProduct); - if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) - { + printf(" iProduct %u ", desc_device.iProduct); + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) { print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf)); } printf("\r\n"); - printf(" iSerialNumber %u " , desc_device.iSerialNumber); - if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) - { + printf(" iSerialNumber %u ", desc_device.iSerialNumber); + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) { print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf)); } printf("\r\n"); - printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations); + printf(" bNumConfigurations %u\r\n", desc_device.bNumConfigurations); // Get configuration descriptor with sync API - if (XFER_RESULT_SUCCESS == tuh_descriptor_get_configuration_sync(daddr, 0, temp_buf, sizeof(temp_buf))) - { - parse_config_descriptor(daddr, (tusb_desc_configuration_t*) temp_buf); + if (XFER_RESULT_SUCCESS == tuh_descriptor_get_configuration_sync(daddr, 0, temp_buf, sizeof(temp_buf))) { + parse_config_descriptor(daddr, (tusb_desc_configuration_t *) temp_buf); } } @@ -171,37 +160,33 @@ uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_ void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); // simple configuration parser to open and listen to HID Endpoint IN -void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) -{ - uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); - uint8_t const* p_desc = tu_desc_next(desc_cfg); +void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const *desc_cfg) { + uint8_t const *desc_end = ((uint8_t const *) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); + uint8_t const *p_desc = tu_desc_next(desc_cfg); // parse each interfaces - while( p_desc < desc_end ) - { + while (p_desc < desc_end) { uint8_t assoc_itf_count = 1; // Class will always starts with Interface Association (if any) and then Interface descriptor - if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) - { - tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; + if (TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc)) { + tusb_desc_interface_assoc_t const *desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; assoc_itf_count = desc_iad->bInterfaceCount; - p_desc = tu_desc_next(p_desc); // next to Interface + p_desc = tu_desc_next(p_desc);// next to Interface } // must be interface from now - if( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) return; - tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; + if (TUSB_DESC_INTERFACE != tu_desc_type(p_desc)) { return; } + tusb_desc_interface_t const *desc_itf = (tusb_desc_interface_t const *) p_desc; - uint16_t const drv_len = count_interface_total_len(desc_itf, assoc_itf_count, (uint16_t) (desc_end-p_desc)); + uint16_t const drv_len = count_interface_total_len(desc_itf, assoc_itf_count, (uint16_t) (desc_end - p_desc)); // probably corrupted descriptor - if(drv_len < sizeof(tusb_desc_interface_t)) return; + if (drv_len < sizeof(tusb_desc_interface_t)) { return; } // only open and listen to HID endpoint IN - if (desc_itf->bInterfaceClass == TUSB_CLASS_HID) - { + if (desc_itf->bInterfaceClass == TUSB_CLASS_HID) { open_hid_interface(dev_addr, desc_itf, drv_len); } @@ -210,25 +195,21 @@ void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* } } -uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) -{ - uint8_t const* p_desc = (uint8_t const*) desc_itf; +uint16_t count_interface_total_len(tusb_desc_interface_t const *desc_itf, uint8_t itf_count, uint16_t max_len) { + uint8_t const *p_desc = (uint8_t const *) desc_itf; uint16_t len = 0; - while (itf_count--) - { + while (itf_count--) { // Next on interface desc len += tu_desc_len(desc_itf); p_desc = tu_desc_next(p_desc); - while (len < max_len) - { + while (len < max_len) { // return on IAD regardless of itf count - if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len; + if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION) { return len; } - if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && - ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) - { + if ((tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && + ((tusb_desc_interface_t const *) p_desc)->bAlternateSetting == 0) { break; } @@ -246,46 +227,45 @@ uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_ void hid_report_received(tuh_xfer_t* xfer); -void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ +void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { // len = interface + hid + n*endpoints uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); // corrupted descriptor - if (max_len < drv_len) return; + if (max_len < drv_len) { return; } uint8_t const *p_desc = (uint8_t const *) desc_itf; // HID descriptor p_desc = tu_desc_next(p_desc); tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc; - if(HID_DESC_TYPE_HID != desc_hid->bDescriptorType) return; + if (HID_DESC_TYPE_HID != desc_hid->bDescriptorType) { return; } // Endpoint descriptor p_desc = tu_desc_next(p_desc); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - for(int i = 0; i < desc_itf->bNumEndpoints; i++) - { - if (TUSB_DESC_ENDPOINT != desc_ep->bDescriptorType) return; + for (int i = 0; i < desc_itf->bNumEndpoints; i++) { + if (TUSB_DESC_ENDPOINT != desc_ep->bDescriptorType) { return; } - if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) - { - // skip if failed to open endpoint - if ( ! tuh_edpt_open(daddr, desc_ep) ) return; + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { + if (!tuh_edpt_open(daddr, desc_ep)) { + return; // skip if failed to open endpoint + } - uint8_t* buf = get_hid_buf(daddr); - if (!buf) return; // out of memory + uint8_t *buf = get_hid_buf(daddr); + if (!buf) { + return;// out of memory + } - tuh_xfer_t xfer = - { - .daddr = daddr, - .ep_addr = desc_ep->bEndpointAddress, - .buflen = 64, - .buffer = buf, - .complete_cb = hid_report_received, - .user_data = (uintptr_t) buf, // since buffer is not available in callback, use user data to store the buffer + tuh_xfer_t xfer = { + .daddr = daddr, + .ep_addr = desc_ep->bEndpointAddress, + .buflen = 64, + .buffer = buf, + .complete_cb = hid_report_received, + .user_data = (uintptr_t) buf,// since buffer is not available in callback, use user data to store the buffer }; // submit transfer for this EP @@ -299,18 +279,17 @@ void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, ui } } -void hid_report_received(tuh_xfer_t* xfer) -{ +void hid_report_received(tuh_xfer_t *xfer) { // Note: not all field in xfer is available for use (i.e filled by tinyusb stack) in callback to save sram // For instance, xfer->buffer is NULL. We have used user_data to store buffer when submitted callback - uint8_t* buf = (uint8_t*) xfer->user_data; + uint8_t *buf = (uint8_t *) xfer->user_data; - if (xfer->result == XFER_RESULT_SUCCESS) - { + if (xfer->result == XFER_RESULT_SUCCESS) { printf("[dev %u: ep %02x] HID Report:", xfer->daddr, xfer->ep_addr); - for(uint32_t i=0; iactual_len; i++) - { - if (i%16 == 0) printf("\r\n "); + for (uint32_t i = 0; i < xfer->actual_len; i++) { + if (i % 16 == 0) { + printf("\r\n "); + } printf("%02X ", buf[i]); } printf("\r\n"); @@ -329,12 +308,9 @@ void hid_report_received(tuh_xfer_t* xfer) //--------------------------------------------------------------------+ // get an buffer from pool -uint8_t* get_hid_buf(uint8_t daddr) -{ - for(size_t i=0; i> 6 & 0x1F)); - *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F)); - } else { - // TODO: Verify surrogate. - *utf8++ = (uint8_t)(0xE0 | (chr >> 12 & 0x0F)); - *utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F)); - *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F)); - } - // TODO: Handle UTF-16 code points that take two entries. + for (size_t i = 0; i < utf16_len; i++) { + uint16_t chr = utf16[i]; + if (chr < 0x80) { + *utf8++ = chr & 0xffu; + } else if (chr < 0x800) { + *utf8++ = (uint8_t) (0xC0 | (chr >> 6 & 0x1F)); + *utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F)); + } else { + // TODO: Verify surrogate. + *utf8++ = (uint8_t) (0xE0 | (chr >> 12 & 0x0F)); + *utf8++ = (uint8_t) (0x80 | (chr >> 6 & 0x3F)); + *utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F)); } + // TODO: Handle UTF-16 code points that take two entries. + } } // Count how many bytes a utf-16-le encoded string will take in utf-8. static int _count_utf8_bytes(const uint16_t *buf, size_t len) { - size_t total_bytes = 0; - for (size_t i = 0; i < len; i++) { - uint16_t chr = buf[i]; - if (chr < 0x80) { - total_bytes += 1; - } else if (chr < 0x800) { - total_bytes += 2; - } else { - total_bytes += 3; - } - // TODO: Handle UTF-16 code points that take two entries. + size_t total_bytes = 0; + for (size_t i = 0; i < len; i++) { + uint16_t chr = buf[i]; + if (chr < 0x80) { + total_bytes += 1; + } else if (chr < 0x800) { + total_bytes += 2; + } else { + total_bytes += 3; } - return (int) total_bytes; + // TODO: Handle UTF-16 code points that take two entries. + } + return (int) total_bytes; } static void print_utf16(uint16_t *temp_buf, size_t buf_len) { - if ((temp_buf[0] & 0xff) == 0) return; // empty - size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); - size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len); - _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); - ((uint8_t*) temp_buf)[utf8_len] = '\0'; + if ((temp_buf[0] & 0xff) == 0) return;// empty + size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); + size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len); + _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); + ((uint8_t *) temp_buf)[utf8_len] = '\0'; - printf("%s", (char*)temp_buf); + printf("%s", (char *) temp_buf); } diff --git a/src/host/hcd.h b/src/host/hcd.h index 56b6fdb5d..aa9e9cf3b 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -165,6 +165,9 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); // Open an endpoint bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * ep_desc); +// Close an endpoint +bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr); + // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); diff --git a/src/host/usbh.c b/src/host/usbh.c index 308916c9b..5925a7be0 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -994,6 +994,12 @@ bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const* desc_ep) { return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, desc_ep); } +bool tuh_edpt_close(uint8_t daddr, uint8_t ep_addr) { + TU_VERIFY(0 != tu_edpt_number(ep_addr)); // cannot close EP0 + tuh_edpt_abort_xfer(daddr, ep_addr); // abort any pending transfer + return hcd_edpt_close(usbh_get_rhport(daddr), daddr, ep_addr); +} + bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) { usbh_device_t* dev = get_device(dev_addr); TU_VERIFY(dev); diff --git a/src/host/usbh.h b/src/host/usbh.h index d95bb9b57..4829a8183 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -33,6 +33,10 @@ #include "common/tusb_common.h" +#if CFG_TUH_MAX3421 +#include "portable/analog/max3421/hcd_max3421.h" +#endif + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -227,6 +231,9 @@ bool tuh_edpt_xfer(tuh_xfer_t* xfer); // Open a non-control endpoint bool tuh_edpt_open(uint8_t daddr, tusb_desc_endpoint_t const * desc_ep); +// Close a non-control endpoint, it will abort any pending transfer +bool tuh_edpt_close(uint8_t daddr, uint8_t ep_addr); + // Abort a queued transfer. Note: it can only abort transfer that has not been started // Return true if a queued transfer is aborted, false if there is no transfer to abort bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr); diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index c5e924266..3fbf950a4 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -252,28 +252,6 @@ static tuh_configure_max3421_t _tuh_cfg = { .pinctl = 0, // default: negative edge interrupt }; -//--------------------------------------------------------------------+ -// API: SPI transfer with MAX3421E -// - spi_cs_api(), spi_xfer_api(), int_api(): must be implemented by application -// - reg_read(), reg_write(): is implemented by this driver, can be used by application -//--------------------------------------------------------------------+ - -// API to control MAX3421 SPI CS -extern void tuh_max3421_spi_cs_api(uint8_t rhport, bool active); - -// API to transfer data with MAX3421 SPI -// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only -extern bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes); - -// API to enable/disable MAX3421 INTR pin interrupt -extern void tuh_max3421_int_api(uint8_t rhport, bool enabled); - -// API to read MAX3421's register. Implemented by TinyUSB -uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr); - -// API to write MAX3421's register. Implemented by TinyUSB -bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr); - //--------------------------------------------------------------------+ // SPI Commands and Helper //--------------------------------------------------------------------+ @@ -632,6 +610,9 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e if (daddr == 0 && ep_num == 0) { ep = &_hcd_data.ep[0]; }else { + if (NULL != find_ep_not_addr0(daddr, ep_num, ep_dir)) { + return false; // endpoint already opened + } ep = allocate_ep(); TU_ASSERT(ep); ep->daddr = daddr; @@ -645,6 +626,21 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e return true; } +bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { + (void) rhport; + uint8_t const ep_num = tu_edpt_number(ep_addr); + tusb_dir_t const ep_dir = tu_edpt_dir(ep_addr); + max3421_ep_t * ep = find_ep_not_addr0(daddr, ep_num, ep_dir); + + if (!ep) { + return false; // not opened + } + + tu_memclr(ep, sizeof(max3421_ep_t)); + + return true; +} + /* The microcontroller repeatedly writes the SNDFIFO register R2 to load the FIFO with up to 64 data bytes. * Then the microcontroller writes the SNDBC register, which this does three things: * 1. Tells the MAX3421E SIE (Serial Interface Engine) how many bytes in the FIFO to send. diff --git a/src/portable/analog/max3421/hcd_max3421.h b/src/portable/analog/max3421/hcd_max3421.h new file mode 100644 index 000000000..4631fa21a --- /dev/null +++ b/src/portable/analog/max3421/hcd_max3421.h @@ -0,0 +1,63 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ +#ifndef TUSB_HCD_MAX3421_H +#define TUSB_HCD_MAX3421_H + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// SPI transfer API with MAX3421E are implemented by application +// - spi_cs_api(), spi_xfer_api(), int_api() +//--------------------------------------------------------------------+ + +// API to control MAX3421 SPI CS +extern void tuh_max3421_spi_cs_api(uint8_t rhport, bool active); + +// API to transfer data with MAX3421 SPI +// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only +extern bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes); + +// API to enable/disable MAX3421 INTR pin interrupt +extern void tuh_max3421_int_api(uint8_t rhport, bool enabled); + +//--------------------------------------------------------------------+ +// API for read/write MAX3421 registers +// are implemented by this driver, can be used by application +//--------------------------------------------------------------------+ + +// API to read MAX3421's register. Implemented by TinyUSB +uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr); + +// API to write MAX3421's register. Implemented by TinyUSB +bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr); + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c index 6422afff1..225a44dcf 100644 --- a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c +++ b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c @@ -122,6 +122,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return pio_usb_host_endpoint_open(pio_rhport, dev_addr, (uint8_t const *) desc_ep, need_pre); } +bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { + uint8_t const pio_rhport = RHPORT_PIO(rhport); + return pio_usb_host_endpoint_close(pio_rhport, daddr, ep_addr); +} + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { uint8_t const pio_rhport = RHPORT_PIO(rhport); return pio_usb_host_endpoint_transfer(pio_rhport, dev_addr, ep_addr, buffer, buflen); diff --git a/tools/get_deps.py b/tools/get_deps.py index 3f529bd7e..ba9dc23ce 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -58,8 +58,8 @@ deps_optional = { 'hw/mcu/nxp/mcux-sdk': ['https://github.com/hathach/mcux-sdk.git', '144f1eb7ea8c06512e12f12b27383601c0272410', 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'], - 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/sekigon-gonnoc/Pico-PIO-USB.git', - '0ca3657d55ea20e7fa4483bbd21ce951bc1d6fa5', + 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/hathach/Pico-PIO-USB.git', + '810653f66adadba3e0e4b4b56d5167ac4f7fdbf7', 'rp2040'], 'hw/mcu/renesas/fsp': ['https://github.com/renesas/fsp.git', 'edcc97d684b6f716728a60d7a6fea049d9870bd6', From 99673cdbb81b76f7020cf6aacb182ea86fdee3da Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 25 Mar 2025 17:36:15 +0700 Subject: [PATCH 087/382] fix wanings --- examples/host/cdc_msc_hid/src/cdc_app.c | 2 +- examples/host/cdc_msc_hid/src/hid_app.c | 3 +-- examples/host/cdc_msc_hid/src/main.c | 12 ++++-------- .../host/cdc_msc_hid_freertos/src/cdc_app.c | 2 +- examples/host/cdc_msc_hid_freertos/src/main.c | 6 ------ .../host/cdc_msc_hid_freertos/src/msc_app.c | 2 +- examples/host/hid_controller/src/hid_app.c | 17 ++++++----------- examples/host/msc_file_explorer/src/msc_app.c | 2 ++ 8 files changed, 16 insertions(+), 30 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index 4a13f8b27..e68ec383b 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -27,7 +27,7 @@ #include "tusb.h" #include "bsp/board_api.h" -size_t get_console_inputs(uint8_t* buf, size_t bufsize) { +static size_t get_console_inputs(uint8_t* buf, size_t bufsize) { size_t count = 0; while (count < bufsize) { int ch = board_getchar(); diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 5bae250cf..a751c9c80 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -165,8 +165,7 @@ static void process_kbd_report(hid_keyboard_report_t const *report) // Mouse //--------------------------------------------------------------------+ -void cursor_movement(int8_t x, int8_t y, int8_t wheel) -{ +static void cursor_movement(int8_t x, int8_t y, int8_t wheel) { #if USE_ANSI_ESCAPE // Move X using ansi escape if ( x < 0) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 2d5df23f9..7b02e238e 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -31,18 +31,12 @@ #include "tusb.h" //--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES +// MACRO CONSTANT TYPEDEF PROTOTYPES //--------------------------------------------------------------------+ void led_blinking_task(void); extern void cdc_app_task(void); extern void hid_app_task(void); -#if CFG_TUH_ENABLED && CFG_TUH_MAX3421 -// API to read/rite MAX3421's register. Implemented by TinyUSB -extern uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr); -extern bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr); -#endif - /*------------- MAIN -------------*/ int main(void) { board_init(); @@ -101,7 +95,9 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < interval_ms) return; // not enough time + if (board_millis() - start_ms < interval_ms) { + return;// not enough time + } start_ms += interval_ms; board_led_write(led_state); diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c index 7cbe1e03a..e279ad509 100644 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -52,7 +52,7 @@ void cdc_app_init(void) { } // helper -size_t get_console_inputs(uint8_t *buf, size_t bufsize) { +static size_t get_console_inputs(uint8_t *buf, size_t bufsize) { size_t count = 0; while (count < bufsize) { int ch = board_getchar(); diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c index 10d1b120b..64a108254 100644 --- a/examples/host/cdc_msc_hid_freertos/src/main.c +++ b/examples/host/cdc_msc_hid_freertos/src/main.c @@ -69,12 +69,6 @@ extern void cdc_app_init(void); extern void hid_app_init(void); extern void msc_app_init(void); -#if CFG_TUH_ENABLED && CFG_TUH_MAX3421 -// API to read/rite MAX3421's register. Implemented by TinyUSB -extern uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr); -extern bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr); -#endif - /*------------- MAIN -------------*/ int main(void) { board_init(); diff --git a/examples/host/cdc_msc_hid_freertos/src/msc_app.c b/examples/host/cdc_msc_hid_freertos/src/msc_app.c index 6b9cdab85..6439495a8 100644 --- a/examples/host/cdc_msc_hid_freertos/src/msc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/msc_app.c @@ -34,7 +34,7 @@ void msc_app_init(void) { // nothing to do } -bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) { +static bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) { msc_cbw_t const *cbw = cb_data->cbw; msc_csw_t const *csw = cb_data->csw; diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c index 6ffe0b6d4..1d6ca8b07 100644 --- a/examples/host/hid_controller/src/hid_app.c +++ b/examples/host/hid_controller/src/hid_app.c @@ -231,14 +231,12 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) } // check if different than 2 -bool diff_than_2(uint8_t x, uint8_t y) -{ +static inline bool diff_than_2(uint8_t x, uint8_t y) { return (x - y > 2) || (y - x > 2); } // check if 2 reports are different enough -bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2) -{ +static bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2) { bool result; // x, y, z, rz must different than 2 to be counted @@ -251,7 +249,7 @@ bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2) return result; } -void process_sony_ds4(uint8_t const* report, uint16_t len) +static void process_sony_ds4(uint8_t const* report, uint16_t len) { (void)len; const char* dpad_str[] = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "none" }; @@ -310,16 +308,13 @@ void process_sony_ds4(uint8_t const* report, uint16_t len) } // Invoked when received report from device via interrupt endpoint -void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) -{ - if ( is_sony_ds4(dev_addr) ) - { +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { + if (is_sony_ds4(dev_addr)) { process_sony_ds4(report, len); } // continue to request to receive report - if ( !tuh_hid_receive_report(dev_addr, instance) ) - { + if (!tuh_hid_receive_report(dev_addr, instance)) { printf("Error: cannot request to receive report\r\n"); } } diff --git a/examples/host/msc_file_explorer/src/msc_app.c b/examples/host/msc_file_explorer/src/msc_app.c index 226c870ea..40a9ef57e 100644 --- a/examples/host/msc_file_explorer/src/msc_app.c +++ b/examples/host/msc_file_explorer/src/msc_app.c @@ -34,6 +34,8 @@ #define EMBEDDED_CLI_IMPL #include "embedded_cli.h" +#include "msc_app.h" + //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION From 73e810a7ba73a54c0bd074e86a18b6e2954057fa Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 Mar 2025 15:20:02 +0700 Subject: [PATCH 088/382] imxrt: disable BOARD_ConfigMPU() since it cause issue with imxrt1060/64. Update imxrt configtool forr some board to get uart pin init. --- hw/bsp/family_support.cmake | 4 - .../mimxrt1015_evk/board/clock_config.c | 4 +- .../mimxrt1015_evk/board/clock_config.h | 66 ++++++------ .../boards/mimxrt1015_evk/board/pin_mux.c | 35 ++++-- .../boards/mimxrt1015_evk/board/pin_mux.h | 30 ++++-- .../boards/mimxrt1015_evk/mimxrt1015_evk.mex | 63 +++++++---- .../mimxrt1064_evk/board/clock_config.c | 4 +- .../mimxrt1064_evk/board/clock_config.h | 100 +++++++++--------- .../boards/mimxrt1064_evk/board/pin_mux.c | 13 +-- .../boards/mimxrt1064_evk/board/pin_mux.h | 1 + .../boards/mimxrt1064_evk/mimxrt1064_evk.mex | 36 +++---- .../mimxrt1170_evkb/board/clock_config.c | 4 +- .../boards/mimxrt1170_evkb/board/pin_mux.c | 56 ++++++---- .../boards/mimxrt1170_evkb/board/pin_mux.h | 27 +++-- .../mimxrt1170_evkb/mimxrt1170_evkb.mex | 75 +++++++------ hw/bsp/imxrt/family.c | 4 +- hw/bsp/imxrt/family.cmake | 4 - 17 files changed, 298 insertions(+), 228 deletions(-) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index e7161eba3..3a6890690 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -270,10 +270,6 @@ function(family_add_tinyusb TARGET OPT_MCU) # Add TinyUSB sources, include and common define tinyusb_target_add(${TARGET}) - - # path to tusb_config.h - target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src) - target_compile_definitions(${TARGET} PUBLIC CFG_TUSB_MCU=${OPT_MCU}) if (DEFINED LOG) target_compile_definitions(${TARGET} PUBLIC CFG_TUSB_DEBUG=${LOG}) diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.c b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.c index ae1aa7fb1..b9e4851bf 100644 --- a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.c +++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.c @@ -15,11 +15,11 @@ /* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* !!GlobalInfo -product: Clocks v11.0 +product: Clocks v15.0 processor: MIMXRT1015xxxxx package_id: MIMXRT1015DAF5A mcu_data: ksdk2_0 -processor_version: 13.0.2 +processor_version: 24.12.10 board: MIMXRT1015-EVK * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.h b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.h index 2acdb16a7..cccbe487a 100644 --- a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.h +++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.h @@ -36,39 +36,39 @@ void BOARD_InitBootClocks(void); #define BOARD_BOOTCLOCKRUN_CORE_CLOCK 500000000U /*!< Core clock frequency: 500000000Hz */ /* Clock outputs (values are in Hz): */ -#define BOARD_BOOTCLOCKRUN_AHB_CLK_ROOT 500000000UL -#define BOARD_BOOTCLOCKRUN_CKIL_SYNC_CLK_ROOT 32768UL -#define BOARD_BOOTCLOCKRUN_CLKO1_CLK 0UL -#define BOARD_BOOTCLOCKRUN_CLKO2_CLK 0UL -#define BOARD_BOOTCLOCKRUN_CLK_1M 1000000UL -#define BOARD_BOOTCLOCKRUN_CLK_24M 24000000UL -#define BOARD_BOOTCLOCKRUN_ENET_500M_REF_CLK 500000000UL -#define BOARD_BOOTCLOCKRUN_FLEXIO1_CLK_ROOT 30000000UL -#define BOARD_BOOTCLOCKRUN_FLEXSPI_CLK_ROOT 196363636UL -#define BOARD_BOOTCLOCKRUN_GPT1_IPG_CLK_HIGHFREQ 62500000UL -#define BOARD_BOOTCLOCKRUN_GPT2_IPG_CLK_HIGHFREQ 62500000UL -#define BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT 125000000UL -#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL -#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL -#define BOARD_BOOTCLOCKRUN_MQS_MCLK 63529411UL -#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 62500000UL -#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI1_MCLK1 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI1_MCLK2 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI1_MCLK3 30000000UL -#define BOARD_BOOTCLOCKRUN_SAI2_CLK_ROOT 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL -#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL -#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL -#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL -#define BOARD_BOOTCLOCKRUN_SPDIF0_CLK_ROOT 30000000UL -#define BOARD_BOOTCLOCKRUN_SPDIF0_EXTCLK_OUT 0UL -#define BOARD_BOOTCLOCKRUN_TRACE_CLK_ROOT 117333333UL -#define BOARD_BOOTCLOCKRUN_UART_CLK_ROOT 80000000UL -#define BOARD_BOOTCLOCKRUN_USBPHY1_CLK 480000000UL +#define BOARD_BOOTCLOCKRUN_AHB_CLK_ROOT 500000000UL /* Clock consumers of AHB_CLK_ROOT output : AIPSTZ1, AIPSTZ2, AIPSTZ3, AIPSTZ4, ARM, FLEXSPI */ +#define BOARD_BOOTCLOCKRUN_CKIL_SYNC_CLK_ROOT 32768UL /* Clock consumers of CKIL_SYNC_CLK_ROOT output : CSU, EWM, GPT1, GPT2, KPP, PIT, RTWDOG, SNVS, SPDIF, TEMPMON, USB, WDOG1, WDOG2 */ +#define BOARD_BOOTCLOCKRUN_CLKO1_CLK 0UL /* Clock consumers of CLKO1_CLK output : N/A */ +#define BOARD_BOOTCLOCKRUN_CLKO2_CLK 0UL /* Clock consumers of CLKO2_CLK output : N/A */ +#define BOARD_BOOTCLOCKRUN_CLK_1M 1000000UL /* Clock consumers of CLK_1M output : EWM, RTWDOG */ +#define BOARD_BOOTCLOCKRUN_CLK_24M 24000000UL /* Clock consumers of CLK_24M output : GPT1, GPT2 */ +#define BOARD_BOOTCLOCKRUN_ENET_500M_REF_CLK 500000000UL /* Clock consumers of ENET_500M_REF_CLK output : N/A */ +#define BOARD_BOOTCLOCKRUN_FLEXIO1_CLK_ROOT 30000000UL /* Clock consumers of FLEXIO1_CLK_ROOT output : FLEXIO1 */ +#define BOARD_BOOTCLOCKRUN_FLEXSPI_CLK_ROOT 196363636UL /* Clock consumers of FLEXSPI_CLK_ROOT output : FLEXSPI */ +#define BOARD_BOOTCLOCKRUN_GPT1_IPG_CLK_HIGHFREQ 62500000UL /* Clock consumers of GPT1_ipg_clk_highfreq output : GPT1 */ +#define BOARD_BOOTCLOCKRUN_GPT2_IPG_CLK_HIGHFREQ 62500000UL /* Clock consumers of GPT2_ipg_clk_highfreq output : GPT2 */ +#define BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT 125000000UL /* Clock consumers of IPG_CLK_ROOT output : ADC1, ADC_ETC, AOI, ARM, BEE, CCM, CSU, DCDC, DCP, DMA0, DMAMUX, ENC1, EWM, FLEXIO1, FLEXRAM, FLEXSPI, GPC, GPIO1, GPIO2, GPIO3, GPIO5, IOMUXC, KPP, LPI2C1, LPI2C2, LPSPI1, LPSPI2, LPUART1, LPUART2, LPUART3, LPUART4, NVIC, OCOTP, PWM1, RTWDOG, SAI1, SAI2, SAI3, SNVS, SPDIF, SRC, TEMPMON, TMR1, TRNG, USB, WDOG1, WDOG2, XBARA, XBARB */ +#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL /* Clock consumers of LPI2C_CLK_ROOT output : LPI2C1, LPI2C2 */ +#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL /* Clock consumers of LPSPI_CLK_ROOT output : LPSPI1, LPSPI2 */ +#define BOARD_BOOTCLOCKRUN_MQS_MCLK 63529411UL /* Clock consumers of MQS_MCLK output : N/A */ +#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 62500000UL /* Clock consumers of PERCLK_CLK_ROOT output : GPT1, GPT2, PIT */ +#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL /* Clock consumers of SAI1_CLK_ROOT output : N/A */ +#define BOARD_BOOTCLOCKRUN_SAI1_MCLK1 63529411UL /* Clock consumers of SAI1_MCLK1 output : SAI1 */ +#define BOARD_BOOTCLOCKRUN_SAI1_MCLK2 63529411UL /* Clock consumers of SAI1_MCLK2 output : SAI1 */ +#define BOARD_BOOTCLOCKRUN_SAI1_MCLK3 30000000UL /* Clock consumers of SAI1_MCLK3 output : SAI1 */ +#define BOARD_BOOTCLOCKRUN_SAI2_CLK_ROOT 63529411UL /* Clock consumers of SAI2_CLK_ROOT output : N/A */ +#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL /* Clock consumers of SAI2_MCLK1 output : SAI2 */ +#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL /* Clock consumers of SAI2_MCLK2 output : SAI2 */ +#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL /* Clock consumers of SAI2_MCLK3 output : SAI2 */ +#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 63529411UL /* Clock consumers of SAI3_CLK_ROOT output : N/A */ +#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 63529411UL /* Clock consumers of SAI3_MCLK1 output : SAI3 */ +#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL /* Clock consumers of SAI3_MCLK2 output : SAI3 */ +#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL /* Clock consumers of SAI3_MCLK3 output : SAI3 */ +#define BOARD_BOOTCLOCKRUN_SPDIF0_CLK_ROOT 30000000UL /* Clock consumers of SPDIF0_CLK_ROOT output : SPDIF */ +#define BOARD_BOOTCLOCKRUN_SPDIF0_EXTCLK_OUT 0UL /* Clock consumers of SPDIF0_EXTCLK_OUT output : SPDIF */ +#define BOARD_BOOTCLOCKRUN_TRACE_CLK_ROOT 117333333UL /* Clock consumers of TRACE_CLK_ROOT output : ARM */ +#define BOARD_BOOTCLOCKRUN_UART_CLK_ROOT 80000000UL /* Clock consumers of UART_CLK_ROOT output : LPUART1, LPUART2, LPUART3, LPUART4 */ +#define BOARD_BOOTCLOCKRUN_USBPHY1_CLK 480000000UL /* Clock consumers of USBPHY1_CLK output : TEMPMON, USB */ /*! @brief Usb1 PLL set for BOARD_BootClockRUN configuration. */ diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.c b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.c index 97224a332..76c1dae70 100644 --- a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.c +++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.c @@ -6,11 +6,11 @@ /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* !!GlobalInfo -product: Pins v13.1 +product: Pins v17.0 processor: MIMXRT1015xxxxx package_id: MIMXRT1015DAF5A mcu_data: ksdk2_0 -processor_version: 13.0.2 +processor_version: 24.12.10 board: MIMXRT1015-EVK external_user_signals: {} pin_labels: @@ -32,6 +32,7 @@ power_domains: {NVCC_GPIO: '3.3'} * END ****************************************************************************************************************/ void BOARD_InitBootPins(void) { BOARD_InitPins(); + BOARD_InitDEBUG_UARTPins(); } /* @@ -40,8 +41,6 @@ BOARD_InitPins: - options: {callFromInitBoot: 'true', coreID: core0, enableClock: 'true'} - pin_list: - {pin_num: '1', peripheral: GPIO2, signal: 'gpio_io, 09', pin_signal: GPIO_EMC_09, direction: INPUT, pull_keeper_select: Pull, pull_up_down_config: Pull_Up_47K_Ohm} - - {pin_num: '68', peripheral: LPUART1, signal: RX, pin_signal: GPIO_AD_B0_07, pull_up_down_config: Pull_Down_100K_Ohm} - - {pin_num: '72', peripheral: LPUART1, signal: TX, pin_signal: GPIO_AD_B0_06} - {pin_num: '21', peripheral: GPIO3, signal: 'gpio_io, 21', pin_signal: GPIO_SD_B1_01, direction: OUTPUT} * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** */ @@ -73,15 +72,11 @@ void BOARD_InitPins(void) { /* Initialize GPIO functionality on GPIO_SD_B1_01 (pin 21) */ GPIO_PinInit(GPIO3, 21U, &USER_LED_config); - IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_06_LPUART1_TX, 0U); - IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_07_LPUART1_RX, 0U); IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_09_GPIO2_IO09, 0U); IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_01_GPIO3_IO21, 0U); - IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_07_LPUART1_RX, 0x10B0U); IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_09_GPIO2_IO09, 0x70B0U); } - /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* BOARD_InitQSPIPins: @@ -113,6 +108,30 @@ void BOARD_InitQSPIPins(void) { IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_11_FLEXSPI_A_SS0_B, 0U); } +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitDEBUG_UARTPins: +- options: {callFromInitBoot: 'true', coreID: core0, enableClock: 'true'} +- pin_list: + - {pin_num: '68', peripheral: LPUART1, signal: RX, pin_signal: GPIO_AD_B0_07, slew_rate: Slow} + - {pin_num: '72', peripheral: LPUART1, signal: TX, pin_signal: GPIO_AD_B0_06, slew_rate: Slow} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitDEBUG_UARTPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitDEBUG_UARTPins(void) { + CLOCK_EnableClock(kCLOCK_Iomuxc); + + IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_06_LPUART1_TX, 0U); + IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_07_LPUART1_RX, 0U); + IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_06_LPUART1_TX, 0x10B0U); + IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_07_LPUART1_RX, 0x10B0U); +} /*********************************************************************************************************************** * EOF **********************************************************************************************************************/ diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.h b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.h index c9cbe3b72..2f3bf2c4c 100644 --- a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.h +++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.h @@ -37,7 +37,7 @@ extern "C" { */ void BOARD_InitBootPins(void); -/* GPIO_EMC_09 (number 1), USER_BUTTON */ +/* GPIO_EMC_09 (number 1), USER_BUTTON/SW4 */ /* Routed pin properties */ #define BOARD_INITPINS_USER_BUTTON_PERIPHERAL GPIO2 /*!< Peripheral name */ #define BOARD_INITPINS_USER_BUTTON_SIGNAL gpio_io /*!< Signal name */ @@ -51,16 +51,6 @@ void BOARD_InitBootPins(void); #define BOARD_INITPINS_USER_BUTTON_PIN 9U /*!< PORT pin number */ #define BOARD_INITPINS_USER_BUTTON_PIN_MASK (1U << 9U) /*!< PORT pin mask */ -/* GPIO_AD_B0_07 (number 68), LPUART1_RXD */ -/* Routed pin properties */ -#define BOARD_INITPINS_UART1_RXD_PERIPHERAL LPUART1 /*!< Peripheral name */ -#define BOARD_INITPINS_UART1_RXD_SIGNAL RX /*!< Signal name */ - -/* GPIO_AD_B0_06 (number 72), LPUART1_TXD */ -/* Routed pin properties */ -#define BOARD_INITPINS_UART1_TXD_PERIPHERAL LPUART1 /*!< Peripheral name */ -#define BOARD_INITPINS_UART1_TXD_SIGNAL TX /*!< Signal name */ - /* GPIO_SD_B1_01 (number 21), GPIO SD_B1_01 */ /* Routed pin properties */ #define BOARD_INITPINS_USER_LED_PERIPHERAL GPIO3 /*!< Peripheral name */ @@ -69,6 +59,7 @@ void BOARD_InitBootPins(void); /* Symbols to be used with GPIO driver */ #define BOARD_INITPINS_USER_LED_GPIO GPIO3 /*!< GPIO peripheral base pointer */ +#define BOARD_INITPINS_USER_LED_INIT_GPIO_VALUE 0U /*!< GPIO output initial state */ #define BOARD_INITPINS_USER_LED_GPIO_PIN 21U /*!< GPIO pin number */ #define BOARD_INITPINS_USER_LED_GPIO_PIN_MASK (1U << 21U) /*!< GPIO pin mask */ #define BOARD_INITPINS_USER_LED_PORT GPIO3 /*!< PORT peripheral base pointer */ @@ -119,6 +110,23 @@ void BOARD_InitPins(void); */ void BOARD_InitQSPIPins(void); +/* GPIO_AD_B0_07 (number 68), LPUART1_RXD */ +/* Routed pin properties */ +#define BOARD_INITDEBUG_UARTPINS_UART1_RXD_PERIPHERAL LPUART1 /*!< Peripheral name */ +#define BOARD_INITDEBUG_UARTPINS_UART1_RXD_SIGNAL RX /*!< Signal name */ + +/* GPIO_AD_B0_06 (number 72), LPUART1_TXD */ +/* Routed pin properties */ +#define BOARD_INITDEBUG_UARTPINS_UART1_TXD_PERIPHERAL LPUART1 /*!< Peripheral name */ +#define BOARD_INITDEBUG_UARTPINS_UART1_TXD_SIGNAL TX /*!< Signal name */ + + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitDEBUG_UARTPins(void); + #if defined(__cplusplus) } #endif diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/mimxrt1015_evk.mex b/hw/bsp/imxrt/boards/mimxrt1015_evk/mimxrt1015_evk.mex index 88265d32e..917bed375 100644 --- a/hw/bsp/imxrt/boards/mimxrt1015_evk/mimxrt1015_evk.mex +++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/mimxrt1015_evk.mex @@ -1,5 +1,5 @@ - + MIMXRT1015xxxxx MIMXRT1015DAF5A @@ -13,19 +13,18 @@ true - false false true false - + - 13.0.2 + 24.12.10 @@ -45,12 +44,7 @@ true - - - true - - - + true @@ -79,12 +73,6 @@ - - - - - - @@ -100,7 +88,7 @@ true - + true @@ -125,15 +113,52 @@ + + Configures pin routing and optionally pin electrical features. + + true + core0 + true + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + - + - 13.0.2 + 24.12.10 diff --git a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.c b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.c index 778ab02f2..be684faee 100644 --- a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.c +++ b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.c @@ -15,11 +15,11 @@ /* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* !!GlobalInfo -product: Clocks v11.0 +product: Clocks v15.0 processor: MIMXRT1064xxxxA package_id: MIMXRT1064DVL6A mcu_data: ksdk2_0 -processor_version: 13.0.2 +processor_version: 24.12.10 board: MIMXRT1064-EVK * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ diff --git a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.h b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.h index 7ce24b6f4..2fa713c0d 100644 --- a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.h +++ b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.h @@ -36,56 +36,56 @@ void BOARD_InitBootClocks(void); #define BOARD_BOOTCLOCKRUN_CORE_CLOCK 600000000U /*!< Core clock frequency: 600000000Hz */ /* Clock outputs (values are in Hz): */ -#define BOARD_BOOTCLOCKRUN_AHB_CLK_ROOT 600000000UL -#define BOARD_BOOTCLOCKRUN_CAN_CLK_ROOT 40000000UL -#define BOARD_BOOTCLOCKRUN_CKIL_SYNC_CLK_ROOT 32768UL -#define BOARD_BOOTCLOCKRUN_CLKO1_CLK 0UL -#define BOARD_BOOTCLOCKRUN_CLKO2_CLK 0UL -#define BOARD_BOOTCLOCKRUN_CLK_1M 1000000UL -#define BOARD_BOOTCLOCKRUN_CLK_24M 24000000UL -#define BOARD_BOOTCLOCKRUN_CSI_CLK_ROOT 12000000UL -#define BOARD_BOOTCLOCKRUN_ENET2_125M_CLK 1200000UL -#define BOARD_BOOTCLOCKRUN_ENET2_REF_CLK 0UL -#define BOARD_BOOTCLOCKRUN_ENET2_TX_CLK 0UL -#define BOARD_BOOTCLOCKRUN_ENET_125M_CLK 2400000UL -#define BOARD_BOOTCLOCKRUN_ENET_25M_REF_CLK 1200000UL -#define BOARD_BOOTCLOCKRUN_ENET_REF_CLK 0UL -#define BOARD_BOOTCLOCKRUN_ENET_TX_CLK 0UL -#define BOARD_BOOTCLOCKRUN_FLEXIO1_CLK_ROOT 30000000UL -#define BOARD_BOOTCLOCKRUN_FLEXIO2_CLK_ROOT 30000000UL -#define BOARD_BOOTCLOCKRUN_FLEXSPI2_CLK_ROOT 130909090UL -#define BOARD_BOOTCLOCKRUN_FLEXSPI_CLK_ROOT 130909090UL -#define BOARD_BOOTCLOCKRUN_GPT1_IPG_CLK_HIGHFREQ 75000000UL -#define BOARD_BOOTCLOCKRUN_GPT2_IPG_CLK_HIGHFREQ 75000000UL -#define BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT 150000000UL -#define BOARD_BOOTCLOCKRUN_LCDIF_CLK_ROOT 67500000UL -#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL -#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL -#define BOARD_BOOTCLOCKRUN_LVDS1_CLK 1200000000UL -#define BOARD_BOOTCLOCKRUN_MQS_MCLK 63529411UL -#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 75000000UL -#define BOARD_BOOTCLOCKRUN_PLL7_MAIN_CLK 480000000UL -#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI1_MCLK1 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI1_MCLK2 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI1_MCLK3 30000000UL -#define BOARD_BOOTCLOCKRUN_SAI2_CLK_ROOT 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL -#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL -#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 63529411UL -#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL -#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL -#define BOARD_BOOTCLOCKRUN_SEMC_CLK_ROOT 75000000UL -#define BOARD_BOOTCLOCKRUN_SPDIF0_CLK_ROOT 30000000UL -#define BOARD_BOOTCLOCKRUN_SPDIF0_EXTCLK_OUT 0UL -#define BOARD_BOOTCLOCKRUN_TRACE_CLK_ROOT 132000000UL -#define BOARD_BOOTCLOCKRUN_UART_CLK_ROOT 80000000UL -#define BOARD_BOOTCLOCKRUN_USBPHY1_CLK 480000000UL -#define BOARD_BOOTCLOCKRUN_USBPHY2_CLK 480000000UL -#define BOARD_BOOTCLOCKRUN_USDHC1_CLK_ROOT 198000000UL -#define BOARD_BOOTCLOCKRUN_USDHC2_CLK_ROOT 198000000UL +#define BOARD_BOOTCLOCKRUN_AHB_CLK_ROOT 600000000UL /* Clock consumers of AHB_CLK_ROOT output : AIPSTZ1, AIPSTZ2, AIPSTZ3, AIPSTZ4, ARM, FLEXIO3, FLEXSPI, FLEXSPI2, GPIO6, GPIO7, GPIO8, GPIO9 */ +#define BOARD_BOOTCLOCKRUN_CAN_CLK_ROOT 40000000UL /* Clock consumers of CAN_CLK_ROOT output : CAN1, CAN2, CAN3 */ +#define BOARD_BOOTCLOCKRUN_CKIL_SYNC_CLK_ROOT 32768UL /* Clock consumers of CKIL_SYNC_CLK_ROOT output : CSU, EWM, GPT1, GPT2, KPP, PIT, RTWDOG, SNVS, SPDIF, TEMPMON, TSC, USB1, USB2, WDOG1, WDOG2 */ +#define BOARD_BOOTCLOCKRUN_CLKO1_CLK 0UL /* Clock consumers of CLKO1_CLK output : N/A */ +#define BOARD_BOOTCLOCKRUN_CLKO2_CLK 0UL /* Clock consumers of CLKO2_CLK output : N/A */ +#define BOARD_BOOTCLOCKRUN_CLK_1M 1000000UL /* Clock consumers of CLK_1M output : EWM, RTWDOG */ +#define BOARD_BOOTCLOCKRUN_CLK_24M 24000000UL /* Clock consumers of CLK_24M output : GPT1, GPT2 */ +#define BOARD_BOOTCLOCKRUN_CSI_CLK_ROOT 12000000UL /* Clock consumers of CSI_CLK_ROOT output : CSI */ +#define BOARD_BOOTCLOCKRUN_ENET2_125M_CLK 1200000UL /* Clock consumers of ENET2_125M_CLK output : N/A */ +#define BOARD_BOOTCLOCKRUN_ENET2_REF_CLK 0UL /* Clock consumers of ENET2_REF_CLK output : ENET2 */ +#define BOARD_BOOTCLOCKRUN_ENET2_TX_CLK 0UL /* Clock consumers of ENET2_TX_CLK output : ENET2 */ +#define BOARD_BOOTCLOCKRUN_ENET_125M_CLK 2400000UL /* Clock consumers of ENET_125M_CLK output : N/A */ +#define BOARD_BOOTCLOCKRUN_ENET_25M_REF_CLK 1200000UL /* Clock consumers of ENET_25M_REF_CLK output : ENET, ENET2 */ +#define BOARD_BOOTCLOCKRUN_ENET_REF_CLK 0UL /* Clock consumers of ENET_REF_CLK output : ENET */ +#define BOARD_BOOTCLOCKRUN_ENET_TX_CLK 0UL /* Clock consumers of ENET_TX_CLK output : ENET */ +#define BOARD_BOOTCLOCKRUN_FLEXIO1_CLK_ROOT 30000000UL /* Clock consumers of FLEXIO1_CLK_ROOT output : FLEXIO1 */ +#define BOARD_BOOTCLOCKRUN_FLEXIO2_CLK_ROOT 30000000UL /* Clock consumers of FLEXIO2_CLK_ROOT output : FLEXIO2, FLEXIO3 */ +#define BOARD_BOOTCLOCKRUN_FLEXSPI2_CLK_ROOT 130909090UL /* Clock consumers of FLEXSPI2_CLK_ROOT output : FLEXSPI2 */ +#define BOARD_BOOTCLOCKRUN_FLEXSPI_CLK_ROOT 130909090UL /* Clock consumers of FLEXSPI_CLK_ROOT output : FLEXSPI */ +#define BOARD_BOOTCLOCKRUN_GPT1_IPG_CLK_HIGHFREQ 75000000UL /* Clock consumers of GPT1_ipg_clk_highfreq output : GPT1 */ +#define BOARD_BOOTCLOCKRUN_GPT2_IPG_CLK_HIGHFREQ 75000000UL /* Clock consumers of GPT2_ipg_clk_highfreq output : GPT2 */ +#define BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT 150000000UL /* Clock consumers of IPG_CLK_ROOT output : ADC1, ADC2, ADC_ETC, AOI1, AOI2, ARM, BEE, CAN1, CAN2, CAN3, CCM, CMP1, CMP2, CMP3, CMP4, CSI, CSU, DCDC, DCP, DMA0, DMAMUX, ENC1, ENC2, ENC3, ENC4, ENET, ENET2, EWM, FLEXIO1, FLEXIO2, FLEXIO3, FLEXRAM, FLEXSPI, FLEXSPI2, GPC, GPIO1, GPIO10, GPIO2, GPIO3, GPIO4, GPIO5, IOMUXC, KPP, LCDIF, LPI2C1, LPI2C2, LPI2C3, LPI2C4, LPSPI1, LPSPI2, LPSPI3, LPSPI4, LPUART1, LPUART2, LPUART3, LPUART4, LPUART5, LPUART6, LPUART7, LPUART8, NVIC, OCOTP, PMU, PWM1, PWM2, PWM3, PWM4, PXP, ROMC, RTWDOG, SAI1, SAI2, SAI3, SNVS, SPDIF, SRC, TEMPMON, TMR1, TMR2, TMR3, TMR4, TRNG, TSC, USB1, USB2, USDHC1, USDHC2, WDOG1, WDOG2, XBARA1, XBARB2, XBARB3 */ +#define BOARD_BOOTCLOCKRUN_LCDIF_CLK_ROOT 67500000UL /* Clock consumers of LCDIF_CLK_ROOT output : LCDIF */ +#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL /* Clock consumers of LPI2C_CLK_ROOT output : LPI2C1, LPI2C2, LPI2C3, LPI2C4 */ +#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL /* Clock consumers of LPSPI_CLK_ROOT output : LPSPI1, LPSPI2, LPSPI3, LPSPI4 */ +#define BOARD_BOOTCLOCKRUN_LVDS1_CLK 1200000000UL /* Clock consumers of LVDS1_CLK output : N/A */ +#define BOARD_BOOTCLOCKRUN_MQS_MCLK 63529411UL /* Clock consumers of MQS_MCLK output : N/A */ +#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 75000000UL /* Clock consumers of PERCLK_CLK_ROOT output : GPT1, GPT2, PIT */ +#define BOARD_BOOTCLOCKRUN_PLL7_MAIN_CLK 480000000UL /* Clock consumers of PLL7_MAIN_CLK output : N/A */ +#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL /* Clock consumers of SAI1_CLK_ROOT output : N/A */ +#define BOARD_BOOTCLOCKRUN_SAI1_MCLK1 63529411UL /* Clock consumers of SAI1_MCLK1 output : SAI1 */ +#define BOARD_BOOTCLOCKRUN_SAI1_MCLK2 63529411UL /* Clock consumers of SAI1_MCLK2 output : SAI1 */ +#define BOARD_BOOTCLOCKRUN_SAI1_MCLK3 30000000UL /* Clock consumers of SAI1_MCLK3 output : SAI1 */ +#define BOARD_BOOTCLOCKRUN_SAI2_CLK_ROOT 63529411UL /* Clock consumers of SAI2_CLK_ROOT output : N/A */ +#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL /* Clock consumers of SAI2_MCLK1 output : SAI2 */ +#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL /* Clock consumers of SAI2_MCLK2 output : SAI2 */ +#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL /* Clock consumers of SAI2_MCLK3 output : SAI2 */ +#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 63529411UL /* Clock consumers of SAI3_CLK_ROOT output : N/A */ +#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 63529411UL /* Clock consumers of SAI3_MCLK1 output : SAI3 */ +#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL /* Clock consumers of SAI3_MCLK2 output : SAI3 */ +#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL /* Clock consumers of SAI3_MCLK3 output : SAI3 */ +#define BOARD_BOOTCLOCKRUN_SEMC_CLK_ROOT 75000000UL /* Clock consumers of SEMC_CLK_ROOT output : SEMC */ +#define BOARD_BOOTCLOCKRUN_SPDIF0_CLK_ROOT 30000000UL /* Clock consumers of SPDIF0_CLK_ROOT output : SPDIF */ +#define BOARD_BOOTCLOCKRUN_SPDIF0_EXTCLK_OUT 0UL /* Clock consumers of SPDIF0_EXTCLK_OUT output : SPDIF */ +#define BOARD_BOOTCLOCKRUN_TRACE_CLK_ROOT 132000000UL /* Clock consumers of TRACE_CLK_ROOT output : ARM */ +#define BOARD_BOOTCLOCKRUN_UART_CLK_ROOT 80000000UL /* Clock consumers of UART_CLK_ROOT output : LPUART1, LPUART2, LPUART3, LPUART4, LPUART5, LPUART6, LPUART7, LPUART8 */ +#define BOARD_BOOTCLOCKRUN_USBPHY1_CLK 480000000UL /* Clock consumers of USBPHY1_CLK output : TEMPMON, USB1 */ +#define BOARD_BOOTCLOCKRUN_USBPHY2_CLK 480000000UL /* Clock consumers of USBPHY2_CLK output : USB2 */ +#define BOARD_BOOTCLOCKRUN_USDHC1_CLK_ROOT 198000000UL /* Clock consumers of USDHC1_CLK_ROOT output : USDHC1 */ +#define BOARD_BOOTCLOCKRUN_USDHC2_CLK_ROOT 198000000UL /* Clock consumers of USDHC2_CLK_ROOT output : USDHC2 */ /*! @brief Arm PLL set for BOARD_BootClockRUN configuration. */ diff --git a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.c b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.c index 8e975dc72..60c4bab37 100644 --- a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.c +++ b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.c @@ -6,11 +6,11 @@ /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* !!GlobalInfo -product: Pins v13.1 +product: Pins v17.0 processor: MIMXRT1064xxxxA package_id: MIMXRT1064DVL6A mcu_data: ksdk2_0 -processor_version: 13.0.2 +processor_version: 24.12.10 board: MIMXRT1064-EVK pin_labels: - {pin_num: F14, pin_signal: GPIO_AD_B0_09, label: 'JTAG_TDI/J21[5]/ENET_RST/J22[5]', identifier: USER_LED} @@ -81,7 +81,6 @@ void BOARD_InitPins(void) { IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0x50A0U); } - /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* BOARD_InitDEBUG_UARTPins: @@ -109,7 +108,6 @@ void BOARD_InitDEBUG_UARTPins(void) { IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_13_LPUART1_RX, 0x10B0U); } - /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* BOARD_InitSDRAMPins: @@ -209,7 +207,6 @@ void BOARD_InitSDRAMPins(void) { IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_39_SEMC_DQS, 0U); } - /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* BOARD_InitCSIPins: @@ -267,7 +264,6 @@ void BOARD_InitCSIPins(void) { IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA, 0xD8B0U); } - /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* BOARD_InitLCDPins: @@ -360,7 +356,6 @@ void BOARD_InitLCDPins(void) { IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_15_GPIO2_IO31, 0x10B0U); } - /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* BOARD_InitCANPins: @@ -384,7 +379,6 @@ void BOARD_InitCANPins(void) { IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_15_FLEXCAN2_RX, 0U); } - /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* BOARD_InitENETPins: @@ -424,7 +418,6 @@ void BOARD_InitENETPins(void) { IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_41_ENET_MDIO, 0U); } - /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* BOARD_InitUSDHCPins: @@ -458,7 +451,6 @@ void BOARD_InitUSDHCPins(void) { IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B0_05_USDHC1_DATA3, 0U); } - /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* BOARD_InitQSPIPins: @@ -491,7 +483,6 @@ void BOARD_InitQSPIPins(void) { IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_10_FLEXSPIA_DATA02, 0U); IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_11_FLEXSPIA_DATA03, 0U); } - /*********************************************************************************************************************** * EOF **********************************************************************************************************************/ diff --git a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.h b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.h index bf494b6f6..be1461f16 100644 --- a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.h +++ b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.h @@ -47,6 +47,7 @@ void BOARD_InitBootPins(void); /* Symbols to be used with GPIO driver */ #define BOARD_INITPINS_USER_LED_GPIO GPIO1 /*!< GPIO peripheral base pointer */ +#define BOARD_INITPINS_USER_LED_INIT_GPIO_VALUE 0U /*!< GPIO output initial state */ #define BOARD_INITPINS_USER_LED_GPIO_PIN 9U /*!< GPIO pin number */ #define BOARD_INITPINS_USER_LED_GPIO_PIN_MASK (1U << 9U) /*!< GPIO pin mask */ #define BOARD_INITPINS_USER_LED_PORT GPIO1 /*!< PORT peripheral base pointer */ diff --git a/hw/bsp/imxrt/boards/mimxrt1064_evk/mimxrt1064_evk.mex b/hw/bsp/imxrt/boards/mimxrt1064_evk/mimxrt1064_evk.mex index 3f0948101..58247fa5b 100644 --- a/hw/bsp/imxrt/boards/mimxrt1064_evk/mimxrt1064_evk.mex +++ b/hw/bsp/imxrt/boards/mimxrt1064_evk/mimxrt1064_evk.mex @@ -1,5 +1,5 @@ - + MIMXRT1064xxxxA MIMXRT1064DVL6A @@ -13,19 +13,18 @@ true - false false true false - + - 13.0.2 + 24.12.10 @@ -41,7 +40,7 @@ true - + true @@ -84,7 +83,7 @@ true - + true @@ -137,7 +136,7 @@ true - + true @@ -204,12 +203,12 @@ true - + true - + true @@ -277,7 +276,7 @@ true - + true @@ -450,7 +449,7 @@ true - + true @@ -479,7 +478,7 @@ true - + true @@ -516,7 +515,7 @@ true - + true @@ -550,7 +549,7 @@ true - + true @@ -578,13 +577,13 @@ - + - 13.0.2 + 24.12.10 @@ -751,10 +750,7 @@ - - - - + 13.0.2 diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/clock_config.c b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/clock_config.c index 66f1f983a..4f06299de 100644 --- a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/clock_config.c +++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/clock_config.c @@ -11,11 +11,11 @@ /* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* !!GlobalInfo -product: Clocks v14.0 +product: Clocks v15.0 processor: MIMXRT1176xxxxx package_id: MIMXRT1176DVMAA mcu_data: ksdk2_0 -processor_version: 16.3.0 +processor_version: 24.12.10 board: MIMXRT1170-EVKB * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.c b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.c index 2c83fb55e..5e8cb91c1 100644 --- a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.c +++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.c @@ -6,11 +6,11 @@ /* * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* !!GlobalInfo -product: Pins v16.0 +product: Pins v17.0 processor: MIMXRT1176xxxxx package_id: MIMXRT1176DVMAA mcu_data: ksdk2_0 -processor_version: 16.3.0 +processor_version: 24.12.10 board: MIMXRT1170-EVKB external_user_signals: {} pin_labels: @@ -31,6 +31,7 @@ pin_labels: * END ****************************************************************************************************************/ void BOARD_InitBootPins(void) { BOARD_InitPins(); + BOARD_InitDEBUG_UARTPins(); } /* @@ -38,10 +39,6 @@ void BOARD_InitBootPins(void) { BOARD_InitPins: - options: {callFromInitBoot: 'true', coreID: cm7, enableClock: 'true'} - pin_list: - - {pin_num: M15, peripheral: LPUART1, signal: RXD, pin_signal: GPIO_AD_25, software_input_on: Disable, pull_up_down_config: Pull_Down, pull_keeper_select: Keeper, - open_drain: Disable, drive_strength: High, slew_rate: Slow} - - {pin_num: L13, peripheral: LPUART1, signal: TXD, pin_signal: GPIO_AD_24, software_input_on: Disable, pull_up_down_config: Pull_Down, pull_keeper_select: Keeper, - open_drain: Disable, drive_strength: High, slew_rate: Slow} - {pin_num: M13, peripheral: GPIO9, signal: 'gpio_io, 03', pin_signal: GPIO_AD_04, identifier: USER_LED, direction: OUTPUT, pull_up_down_config: Pull_Down, pull_keeper_select: Keeper} - {pin_num: T8, peripheral: GPIO13, signal: 'gpio_io, 00', pin_signal: WAKEUP, direction: INPUT, pull_up_down_config: Pull_Up} * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** @@ -77,12 +74,6 @@ void BOARD_InitPins(void) { IOMUXC_SetPinMux( IOMUXC_GPIO_AD_04_GPIO9_IO03, /* GPIO_AD_04 is configured as GPIO9_IO03 */ 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_AD_24_LPUART1_TXD, /* GPIO_AD_24 is configured as LPUART1_TXD */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_AD_25_LPUART1_RXD, /* GPIO_AD_25 is configured as LPUART1_RXD */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ IOMUXC_SetPinMux( IOMUXC_WAKEUP_DIG_GPIO13_IO00, /* WAKEUP_DIG is configured as GPIO13_IO00 */ 0U); /* Software Input On Field: Input Path is determined by functionality */ @@ -95,6 +86,40 @@ void BOARD_InitPins(void) { Open Drain Field: Disabled Domain write protection: Both cores are allowed Domain write protection lock: Neither of DWP bits is locked */ + IOMUXC_SetPinConfig( + IOMUXC_WAKEUP_DIG_GPIO13_IO00, /* WAKEUP_DIG PAD functional properties : */ + 0x0EU); /* Pull / Keep Select Field: Pull Enable + Pull Up / Down Config. Field: Weak pull up + Open Drain SNVS Field: Disabled + Domain write protection: Both cores are allowed + Domain write protection lock: Neither of DWP bits is locked */ +} + +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitDEBUG_UARTPins: +- options: {callFromInitBoot: 'true', coreID: cm7, enableClock: 'true'} +- pin_list: + - {pin_num: L13, peripheral: LPUART1, signal: TXD, pin_signal: GPIO_AD_24, pull_keeper_select: Keeper, slew_rate: Slow} + - {pin_num: M15, peripheral: LPUART1, signal: RXD, pin_signal: GPIO_AD_25, pull_keeper_select: Keeper, slew_rate: Slow} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitDEBUG_UARTPins, assigned for the Cortex-M7F core. + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitDEBUG_UARTPins(void) { + CLOCK_EnableClock(kCLOCK_Iomuxc); /* LPCG on: LPCG is ON. */ + + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_24_LPUART1_TXD, /* GPIO_AD_24 is configured as LPUART1_TXD */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_25_LPUART1_RXD, /* GPIO_AD_25 is configured as LPUART1_RXD */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ IOMUXC_SetPinConfig( IOMUXC_GPIO_AD_24_LPUART1_TXD, /* GPIO_AD_24 PAD functional properties : */ 0x02U); /* Slew Rate Field: Slow Slew Rate @@ -113,13 +138,6 @@ void BOARD_InitPins(void) { Open Drain Field: Disabled Domain write protection: Both cores are allowed Domain write protection lock: Neither of DWP bits is locked */ - IOMUXC_SetPinConfig( - IOMUXC_WAKEUP_DIG_GPIO13_IO00, /* WAKEUP_DIG PAD functional properties : */ - 0x0EU); /* Pull / Keep Select Field: Pull Enable - Pull Up / Down Config. Field: Weak pull up - Open Drain SNVS Field: Disabled - Domain write protection: Both cores are allowed - Domain write protection lock: Neither of DWP bits is locked */ } /*********************************************************************************************************************** * EOF diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.h b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.h index a5b621476..0e0368ef6 100644 --- a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.h +++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.h @@ -25,16 +25,6 @@ extern "C" { */ void BOARD_InitBootPins(void); -/* GPIO_AD_25 (coord M15), LPUART1_RXD */ -/* Routed pin properties */ -#define BOARD_INITPINS_LPUART1_RXD_PERIPHERAL LPUART1 /*!< Peripheral name */ -#define BOARD_INITPINS_LPUART1_RXD_SIGNAL RXD /*!< Signal name */ - -/* GPIO_AD_24 (coord L13), LPUART1_TXD */ -/* Routed pin properties */ -#define BOARD_INITPINS_LPUART1_TXD_PERIPHERAL LPUART1 /*!< Peripheral name */ -#define BOARD_INITPINS_LPUART1_TXD_SIGNAL TXD /*!< Signal name */ - /* GPIO_AD_04 (coord M13), SIM1_PD/J44[C8]/USER_LED_CTL1/J9[8]/J25[7] */ /* Routed pin properties */ #define BOARD_INITPINS_USER_LED_PERIPHERAL GPIO9 /*!< Peripheral name */ @@ -43,6 +33,7 @@ void BOARD_InitBootPins(void); /* Symbols to be used with GPIO driver */ #define BOARD_INITPINS_USER_LED_GPIO GPIO9 /*!< GPIO peripheral base pointer */ +#define BOARD_INITPINS_USER_LED_INIT_GPIO_VALUE 0U /*!< GPIO output initial state */ #define BOARD_INITPINS_USER_LED_GPIO_PIN 3U /*!< GPIO pin number */ #define BOARD_INITPINS_USER_LED_GPIO_PIN_MASK (1U << 3U) /*!< GPIO pin mask */ @@ -63,6 +54,22 @@ void BOARD_InitBootPins(void); */ void BOARD_InitPins(void); /* Function assigned for the Cortex-M7F */ +/* GPIO_AD_24 (coord L13), LPUART1_TXD */ +/* Routed pin properties */ +#define BOARD_INITDEBUG_UARTPINS_LPUART1_TXD_PERIPHERAL LPUART1 /*!< Peripheral name */ +#define BOARD_INITDEBUG_UARTPINS_LPUART1_TXD_SIGNAL TXD /*!< Signal name */ + +/* GPIO_AD_25 (coord M15), LPUART1_RXD */ +/* Routed pin properties */ +#define BOARD_INITDEBUG_UARTPINS_LPUART1_RXD_PERIPHERAL LPUART1 /*!< Peripheral name */ +#define BOARD_INITDEBUG_UARTPINS_LPUART1_RXD_SIGNAL RXD /*!< Signal name */ + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitDEBUG_UARTPins(void); /* Function assigned for the Cortex-M7F */ + #if defined(__cplusplus) } #endif diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/mimxrt1170_evkb.mex b/hw/bsp/imxrt/boards/mimxrt1170_evkb/mimxrt1170_evkb.mex index a4c8917f7..de6b12394 100644 --- a/hw/bsp/imxrt/boards/mimxrt1170_evkb/mimxrt1170_evkb.mex +++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/mimxrt1170_evkb.mex @@ -1,5 +1,5 @@ - + MIMXRT1176xxxxx MIMXRT1176DVMAA @@ -13,19 +13,18 @@ true - false false true false - + - 16.3.0 + 24.12.10 @@ -43,11 +42,6 @@ true - - - true - - true @@ -65,26 +59,6 @@ - - - - - - - - - - - - - - - - - - - - @@ -101,15 +75,54 @@ + + Configures pin routing and optionally pin electrical features. + + true + cm7 + true + + + + + true + + + + + true + + + + + true + + + + + + + + + + + + + + + + + + - + - 16.3.0 + 24.12.10 diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c index ad529a227..eaaf83c03 100644 --- a/hw/bsp/imxrt/family.c +++ b/hw/bsp/imxrt/family.c @@ -109,8 +109,8 @@ static void init_usb_phy(uint8_t usb_id) { } void board_init(void) { - BOARD_ConfigMPU(); - BOARD_InitPins(); + // BOARD_ConfigMPU(); + BOARD_InitBootPins(); BOARD_BootClockRUN(); SystemCoreClockUpdate(); diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index f08ccb3e5..6224b63a4 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -123,8 +123,6 @@ function(family_configure_example TARGET RTOS) # Board target add_board_target(board_${BOARD}) - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h target_sources(${TARGET} PUBLIC # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c @@ -146,8 +144,6 @@ function(family_configure_example TARGET RTOS) ) target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - # Flashing family_add_bin_hex(${TARGET}) family_flash_jlink(${TARGET}) From 69dca9518c516c48ad013ea00c11bbf1746ada9a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 Mar 2025 15:20:27 +0700 Subject: [PATCH 089/382] added mimxrt1064_evk to hil test pool --- examples/dual/host_info_to_device_cdc/src/main.c | 3 ++- test/hil/hil_test.py | 3 +++ test/hil/tinyusb.json | 13 +++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/examples/dual/host_info_to_device_cdc/src/main.c b/examples/dual/host_info_to_device_cdc/src/main.c index c1017141c..7e593f234 100644 --- a/examples/dual/host_info_to_device_cdc/src/main.c +++ b/examples/dual/host_info_to_device_cdc/src/main.c @@ -142,7 +142,7 @@ void cdc_task(void) { if (!tud_cdc_connected()) { // delay a bit otherwise we can outpace host's terminal. Linux will set LineState (DTR) then Line Coding. // If we send data before Linux's terminal set Line Coding, it can be ignored --> missing data with hardware test loop - board_delay(10); + board_delay(20); return; } @@ -151,6 +151,7 @@ void cdc_task(void) { if (is_print[daddr]) { is_print[daddr] = false; print_device_info(daddr, &descriptor_device[daddr]); + tud_cdc_write_flush(); } } } diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 017c17018..662bb3a1f 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -561,6 +561,9 @@ def test_board(board): print('Skip (no binary)') continue + if verbose: + print(f'Flashing {fw_name}.elf') + # flash firmware. It may fail randomly, retry a few times max_rety = 2 for i in range(max_rety): diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index 7436ddb63..a9460bf9d 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -69,6 +69,19 @@ "args": "-device ATSAMD51J19" } }, + { + "name": "mimxrt1064_evk", + "uid": "BAE96FB95AFA6DBB8F00005002001200", + "tests": { + "device": true, "host": true, "dual": true, + "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2023299"}] + }, + "flasher": { + "name": "jlink", + "uid": "000725299165", + "args": "-device MIMXRT1064xxx6A" + } + }, { "name": "lpcxpresso11u37", "uid": "17121919", From 1615120bca3c482b7ba3b2d5620393354acf9c81 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 Mar 2025 15:32:19 +0700 Subject: [PATCH 090/382] added mimxrt1064_evk to hil test pool --- hw/bsp/imxrt/family.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c index eaaf83c03..7b89cc76d 100644 --- a/hw/bsp/imxrt/family.c +++ b/hw/bsp/imxrt/family.c @@ -258,6 +258,7 @@ void _exit(int __status) { //-------------------------------------------------------------------- // MPU configuration //-------------------------------------------------------------------- +#if 0 // TODO move to per board specific #if __CORTEX_M == 7 static void BOARD_ConfigMPU(void) { #if defined(__CC_ARM) || defined(__ARMCC_VERSION) @@ -636,3 +637,4 @@ void BOARD_ConfigMPU(void) { LMEM->PCCCR |= LMEM_PCCCR_ENCACHE_MASK; } #endif +#endif From 901ce2ad93b39c08e8e6b7e5b3f4dbd0b9df879e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 Mar 2025 21:13:01 +0700 Subject: [PATCH 091/382] hcd/ehci: hcd_edpt_open() return false if ep is already opened. implement hcd_edpt_close() --- hw/bsp/imxrt/family.c | 4 +- src/device/usbd.c | 9 +- src/host/usbh.c | 2 +- src/portable/ehci/ehci.c | 259 +++++++++++++++++++----------------- src/portable/ehci/ehci.h | 280 +++++++++++++++++++-------------------- test/hil/hil_test.py | 3 +- 6 files changed, 284 insertions(+), 273 deletions(-) diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c index 7b89cc76d..7e4734a66 100644 --- a/hw/bsp/imxrt/family.c +++ b/hw/bsp/imxrt/family.c @@ -61,7 +61,7 @@ - Define CFG_TUSB_MEM_SECTION=__attribute__((section("NonCacheable"))) */ -static void BOARD_ConfigMPU(void); +// static void BOARD_ConfigMPU(void); // needed by fsl_flexspi_nor_boot TU_ATTR_USED const uint8_t dcd_data[] = {0x00}; @@ -456,7 +456,7 @@ static void BOARD_ConfigMPU(void) { #elif __CORTEX_M == 4 -void BOARD_ConfigMPU(void) { +static void BOARD_ConfigMPU(void) { #if defined(__CC_ARM) || defined(__ARMCC_VERSION) extern uint32_t Image$$RW_m_ncache$$Base[]; /* RW_m_ncache_unused is a auxiliary region which is used to get the whole size of noncache section */ diff --git a/src/device/usbd.c b/src/device/usbd.c index fb5cec49d..9c381d5e0 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -561,8 +561,7 @@ static void usbd_reset(uint8_t rhport) { } bool tud_task_event_ready(void) { - // Skip if stack is not initialized - if (!tud_inited()) return false; + TU_VERIFY(tud_inited()); // Skip if stack is not initialized return !osal_queue_empty(_usbd_q); } @@ -684,7 +683,9 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { case USBD_EVENT_FUNC_CALL: TU_LOG_USBD("\r\n"); - if (event.func_call.func) event.func_call.func(event.func_call.param); + if (event.func_call.func) { + event.func_call.func(event.func_call.param); + } break; case DCD_EVENT_SOF: @@ -701,7 +702,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { #if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO // return if there is no more events, for application to run other background - if (osal_queue_empty(_usbd_q)) return; + if (osal_queue_empty(_usbd_q)) { return; } #endif } } diff --git a/src/host/usbh.c b/src/host/usbh.c index 5925a7be0..e60db53da 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -520,7 +520,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { // Loop until there is no more events in the queue while (1) { hcd_event_t event; - if (!osal_queue_receive(_usbh_q, &event, timeout_ms)) return; + if (!osal_queue_receive(_usbh_q, &event, timeout_ms)) { return; } switch (event.event_id) { case HCD_EVENT_DEVICE_ATTACH: diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 01bbf62bf..292a352fb 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -62,8 +62,7 @@ #define QHD_MAX (CFG_TUH_DEVICE_MAX*CFG_TUH_ENDPOINT_MAX + CFG_TUH_HUB) #define QTD_MAX QHD_MAX -typedef struct -{ +typedef struct { ehci_link_t period_framelist[FRAMELIST_SIZE]; // TODO only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) @@ -139,6 +138,12 @@ static ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr); static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); static void qhd_attach_qtd(ehci_qhd_t *qhd, ehci_qtd_t *qtd); static void qhd_remove_qtd(ehci_qhd_t *qhd); +TU_ATTR_ALWAYS_INLINE static inline bool qhd_is_periodic(ehci_qhd_t const *qhd) { + return qhd->int_smask != 0; +} +TU_ATTR_ALWAYS_INLINE static inline uint8_t qhd_ep_addr(ehci_qhd_t const *qhd) { + return tu_edpt_addr(qhd->ep_number, qhd->pid); +} TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t* qtd_control(uint8_t dev_addr); TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t* qtd_find_free (void); @@ -146,9 +151,10 @@ static void qtd_init (ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes) TU_ATTR_ALWAYS_INLINE static inline ehci_link_t* list_get_period_head(uint8_t rhport, uint32_t interval_ms); TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t* list_get_async_head(uint8_t rhport); -TU_ATTR_ALWAYS_INLINE static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type); TU_ATTR_ALWAYS_INLINE static inline ehci_link_t* list_next (ehci_link_t const *p_link); -static void list_remove_qhd_by_daddr(ehci_link_t* list_head, uint8_t dev_addr); +TU_ATTR_ALWAYS_INLINE static inline void list_insert (ehci_link_t *current, ehci_link_t *entry, uint8_t type); +TU_ATTR_ALWAYS_INLINE static inline void list_remove(ehci_link_t* head, ehci_link_t* prev, ehci_qhd_t* qhd); +static void list_remove_qhd_by_addr(ehci_link_t *list_head, uint8_t dev_addr, uint8_t ep_addr); static void ehci_disable_schedule(ehci_registers_t* regs, bool is_period) { // maybe have a timeout for status @@ -175,15 +181,12 @@ static void ehci_enable_schedule(ehci_registers_t* regs, bool is_period) { //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ - -uint32_t hcd_frame_number(uint8_t rhport) -{ +uint32_t hcd_frame_number(uint8_t rhport) { (void) rhport; return (ehci_data.uframe_number + ehci_data.regs->frame_index) >> 3; } -void hcd_port_reset(uint8_t rhport) -{ +void hcd_port_reset(uint8_t rhport) { (void) rhport; ehci_registers_t* regs = ehci_data.regs; @@ -204,8 +207,7 @@ void hcd_port_reset(uint8_t rhport) regs->portsc = portsc; } -void hcd_port_reset_end(uint8_t rhport) -{ +void hcd_port_reset_end(uint8_t rhport) { (void) rhport; ehci_registers_t* regs = ehci_data.regs; @@ -221,32 +223,29 @@ void hcd_port_reset_end(uint8_t rhport) regs->portsc = portsc; } -bool hcd_port_connect_status(uint8_t rhport) -{ +bool hcd_port_connect_status(uint8_t rhport) { (void) rhport; return ehci_data.regs->portsc_bm.current_connect_status; } -tusb_speed_t hcd_port_speed_get(uint8_t rhport) -{ +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { (void) rhport; return (tusb_speed_t) ehci_data.regs->portsc_bm.nxp_port_speed; // NXP specific port speed } // Close all opened endpoint belong to this device -void hcd_device_close(uint8_t rhport, uint8_t daddr) -{ +void hcd_device_close(uint8_t rhport, uint8_t daddr) { // skip dev0 if (daddr == 0) { return; } - // Remove from async list - list_remove_qhd_by_daddr((ehci_link_t *) list_get_async_head(rhport), daddr); + // Remove from async list all endpoints of this device + list_remove_qhd_by_addr((ehci_link_t *) list_get_async_head(rhport), daddr, TUSB_INDEX_INVALID_8); - // Remove from all interval period list - for(uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++) { - list_remove_qhd_by_daddr((ehci_link_t *) &ehci_data.period_head_arr[i], daddr); + // Remove from all interval period list of this device + for (uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++) { + list_remove_qhd_by_addr((ehci_link_t *) &ehci_data.period_head_arr[i], daddr, TUSB_INDEX_INVALID_8); } // Async doorbell (EHCI 4.8.2 for operational details) @@ -358,12 +357,10 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg) } #if 0 -static void ehci_stop(uint8_t rhport) -{ +static void ehci_stop(uint8_t rhport) { (void) rhport; ehci_registers_t* regs = ehci_data.regs; - regs->command_bm.run_stop = 0; // USB Spec: controller has to stop within 16 uframe = 2 frames @@ -375,41 +372,44 @@ static void ehci_stop(uint8_t rhport) // Endpoint API //--------------------------------------------------------------------+ -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -{ - (void) rhport; - +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { // TODO not support ISO yet TU_ASSERT (ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); //------------- Prepare Queue Head -------------// - ehci_qhd_t *p_qhd = (ep_desc->bEndpointAddress == 0) ? qhd_control(dev_addr) : qhd_find_free(); + ehci_qhd_t *p_qhd; + if (ep_desc->bEndpointAddress == 0) { + p_qhd = qhd_control(dev_addr); + } else { + TU_VERIFY(NULL == qhd_get_from_addr(dev_addr, ep_desc->bEndpointAddress)); // ep not opened yet + p_qhd = qhd_find_free(); + } TU_ASSERT(p_qhd); - qhd_init(p_qhd, dev_addr, ep_desc); - // control of dev0 is always present as async head - if ( dev_addr == 0 ) return true; + // control of dev0 always exists as async head + if (dev_addr == 0) { + return true; + } // Insert to list ehci_link_t * list_head = NULL; - - switch (ep_desc->bmAttributes.xfer) - { + switch (ep_desc->bmAttributes.xfer) { case TUSB_XFER_CONTROL: case TUSB_XFER_BULK: - list_head = (ehci_link_t*) list_get_async_head(rhport); - break; + list_head = (ehci_link_t *) list_get_async_head(rhport); + break; case TUSB_XFER_INTERRUPT: list_head = list_get_period_head(rhport, p_qhd->interval_ms); - break; + break; case TUSB_XFER_ISOCHRONOUS: // TODO iso is not supported - break; + break; - default: break; + default: + break; } TU_ASSERT(list_head); @@ -421,8 +421,23 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ +bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { + ehci_qhd_t* qhd = qhd_get_from_addr(daddr, ep_addr); + TU_VERIFY(qhd != NULL); + + ehci_link_t * list_head; + if (qhd_is_periodic(qhd)) { + // interrupt endpoint + list_head = list_get_period_head(rhport, qhd->interval_ms);; + } else { + list_head = (ehci_link_t *) list_get_async_head(rhport); + } + + list_remove_qhd_by_addr(list_head, daddr, ep_addr); + return true; +} + +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { (void) rhport; ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; @@ -444,14 +459,14 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet return true; } -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) -{ +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); ehci_qhd_t* qhd = qhd_get_from_addr(dev_addr, ep_addr); + TU_VERIFY(qhd != NULL); ehci_qtd_t* qtd; if (epnum == 0) { @@ -540,8 +555,7 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { // This isr mean it is safe to modify previously removed queue head from async list. // In tinyusb, queue head is only removed when device is unplugged. TU_ATTR_ALWAYS_INLINE static inline -void async_advance_isr(uint8_t rhport) -{ +void async_advance_isr(uint8_t rhport) { (void) rhport; ehci_qhd_t *qhd_pool = ehci_data.qhd_pool; @@ -612,8 +626,7 @@ void qhd_xfer_complete_isr(ehci_qhd_t * qhd) { } TU_ATTR_ALWAYS_INLINE static inline -void proccess_async_xfer_isr(ehci_qhd_t * const list_head) -{ +void proccess_async_xfer_isr(ehci_qhd_t * const list_head) { ehci_qhd_t *qhd = list_head; do { @@ -623,8 +636,7 @@ void proccess_async_xfer_isr(ehci_qhd_t * const list_head) } TU_ATTR_ALWAYS_INLINE static inline -void process_period_xfer_isr(uint8_t rhport, uint32_t interval_ms) -{ +void process_period_xfer_isr(uint8_t rhport, uint32_t interval_ms) { uint32_t const period_1ms_addr = (uint32_t) list_get_period_head(rhport, 1u); ehci_link_t next_link = *list_get_period_head(rhport, interval_ms); @@ -726,51 +738,55 @@ TU_ATTR_ALWAYS_INLINE static inline ehci_link_t* list_next(ehci_link_t const *p_ return (ehci_link_t*) tu_align32(p_link->address); } -TU_ATTR_ALWAYS_INLINE static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type) -{ - new->address = current->address; - current->address = ((uint32_t) new) | (new_type << 1); +TU_ATTR_ALWAYS_INLINE static inline void list_insert(ehci_link_t *current, ehci_link_t *entry, uint8_t type) { + entry->address = current->address; + current->address = ((uint32_t) entry) | (type << 1); } -// Remove all queue head belong to this device address -static void list_remove_qhd_by_daddr(ehci_link_t* list_head, uint8_t dev_addr) { - ehci_link_t* prev = list_head; +// Remove a queue head from the list. +// Per EHCI 4.8.2 the removed qhd's next is linked to list head (which always reachable by Host Controller) +// TODO support iTD/siTD +TU_ATTR_ALWAYS_INLINE static inline void list_remove(ehci_link_t* head, ehci_link_t* prev, ehci_qhd_t* qhd) { + // TODO deactivate all TD, wait for QHD to inactive before removal + prev->address = qhd->next.address; + + // link the removed qhd's next to list head + qhd->next.address = ((uint32_t) head) | (EHCI_QTYPE_QHD << 1); + + if (qhd_is_periodic(qhd)) { + // period list queue element is guarantee to be free in the next frame (1 ms) + qhd->used = 0; + } else { + // async list use async advance handshake. Mark as removing, will completely re-usable when async advance isr occurs + qhd->removing = 1; + } + + hcd_dcache_clean(qhd, sizeof(ehci_qhd_t)); + hcd_dcache_clean(prev, sizeof(ehci_qhd_t)); +} + +// Remove queue head belong to this device address +static void list_remove_qhd_by_addr(ehci_link_t *list_head, uint8_t dev_addr, uint8_t ep_addr) { + ehci_link_t *prev = list_head; while (prev && !prev->terminate) { - ehci_qhd_t* qhd = (ehci_qhd_t*) (uintptr_t) list_next(prev); + ehci_qhd_t *qhd = (ehci_qhd_t *) (uintptr_t) list_next(prev); // done if loop back to head - if ( (uintptr_t) qhd == (uintptr_t) list_head) { + if ((uintptr_t) qhd == (uintptr_t) list_head) { break; } - if ( qhd->dev_addr == dev_addr ) { - // TODO deactivate all TD, wait for QHD to inactive before removal - prev->address = qhd->next.address; - - // EHCI 4.8.2 link the removed qhd's next to async head (which always reachable by Host Controller) - qhd->next.address = ((uint32_t) list_head) | (EHCI_QTYPE_QHD << 1); - - if ( qhd->int_smask ) - { - // period list queue element is guarantee to be free in the next frame (1 ms) - qhd->used = 0; - }else - { - // async list use async advance handshake - // mark as removing, will completely re-usable when async advance isr occurs - qhd->removing = 1; - } - - hcd_dcache_clean(qhd, sizeof(ehci_qhd_t)); - hcd_dcache_clean(prev, sizeof(ehci_qhd_t)); - }else { + // ep_addr is 0xff means all endpoints of this device address + if (qhd->dev_addr == dev_addr && + (ep_addr == TUSB_INDEX_INVALID_8 || qhd_ep_addr(qhd) == ep_addr)) { + list_remove(list_head, prev, qhd); + } else { prev = list_next(prev); } } } - //--------------------------------------------------------------------+ // Queue Header helper //--------------------------------------------------------------------+ @@ -782,8 +798,10 @@ TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t* qhd_control(uint8_t dev_addr) { // Find a free queue head TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t *qhd_find_free(void) { - for ( uint32_t i = 0; i < QHD_MAX; i++ ) { - if ( !ehci_data.qhd_pool[i].used ) return &ehci_data.qhd_pool[i]; + for (uint32_t i = 0; i < QHD_MAX; i++) { + if (!ehci_data.qhd_pool[i].used) { + return &ehci_data.qhd_pool[i]; + } } return NULL; } @@ -800,10 +818,9 @@ static ehci_qhd_t *qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) { } ehci_qhd_t *qhd_pool = ehci_data.qhd_pool; - - for ( uint32_t i = 0; i < QHD_MAX; i++ ) { - if ( (qhd_pool[i].dev_addr == dev_addr) && - ep_addr == tu_edpt_addr(qhd_pool[i].ep_number, qhd_pool[i].pid) ) { + for (uint32_t i = 0; i < QHD_MAX; i++) { + if ((qhd_pool[i].dev_addr == dev_addr) && + ep_addr == qhd_ep_addr(&qhd_pool[i])) { return &qhd_pool[i]; } } @@ -812,8 +829,7 @@ static ehci_qhd_t *qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) { } // Init queue head with endpoint descriptor -static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -{ +static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { // address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise) if (dev_addr != 0) { tu_memclr(p_qhd, sizeof(ehci_qhd_t)); @@ -830,39 +846,43 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c p_qhd->ep_number = tu_edpt_number(ep_desc->bEndpointAddress); p_qhd->ep_speed = devtree_info.speed; p_qhd->data_toggle_control= (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0; - p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head + p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static async list head p_qhd->max_packet_size = tu_edpt_packet_size(ep_desc); p_qhd->fl_ctrl_ep_flag = ((xfer_type == TUSB_XFER_CONTROL) && (p_qhd->ep_speed != TUSB_SPEED_HIGH)) ? 1 : 0; p_qhd->nak_reload = 0; - // Bulk/Control -> smask = cmask = 0 - // TODO Isochronous - if (TUSB_XFER_INTERRUPT == xfer_type) - { - if (TUSB_SPEED_HIGH == p_qhd->ep_speed) - { - TU_ASSERT( interval <= 16, ); - if ( interval < 4) // sub millisecond interval - { - p_qhd->interval_ms = 0; - p_qhd->int_smask = (interval == 1) ? TU_BIN8(11111111) : - (interval == 2) ? TU_BIN8(10101010) : TU_BIN8(01000100); - }else - { - p_qhd->interval_ms = (uint8_t) tu_min16( 1 << (interval-4), 255 ); - p_qhd->int_smask = TU_BIT(interval % 8); + switch (xfer_type) { + case TUSB_XFER_CONTROL: + case TUSB_XFER_BULK: + p_qhd->int_smask = p_qhd->fl_int_cmask = 0; + break; + + case TUSB_XFER_INTERRUPT: + if (TUSB_SPEED_HIGH == p_qhd->ep_speed) { + TU_ASSERT(interval <= 16, ); + if (interval < 4) { + // sub millisecond interval + p_qhd->interval_ms = 0; + p_qhd->int_smask = (interval == 1) ? TU_BIN8(11111111) : + (interval == 2) ? TU_BIN8(10101010): TU_BIN8(01000100); + } else { + p_qhd->interval_ms = (uint8_t) tu_min16(1 << (interval - 4), 255); + p_qhd->int_smask = TU_BIT(interval % 8); + } + } else { + TU_ASSERT(0 != interval, ); + // Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes + p_qhd->int_smask = 0x01; + p_qhd->fl_int_cmask = TU_BIN8(11100); + p_qhd->interval_ms = interval; } - }else - { - TU_ASSERT( 0 != interval, ); - // Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes - p_qhd->int_smask = 0x01; - p_qhd->fl_int_cmask = TU_BIN8(11100); - p_qhd->interval_ms = interval; - } - }else - { - p_qhd->int_smask = p_qhd->fl_int_cmask = 0; + break; + + case TUSB_XFER_ISOCHRONOUS: + // TODO not support ISO yet + break; + + default: break; } p_qhd->fl_hub_addr = devtree_info.hub_addr; @@ -880,8 +900,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c p_qhd->qtd_overlay.next.terminate = 1; p_qhd->qtd_overlay.alternate.terminate = 1; - if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid == EHCI_PID_OUT) - { + if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid == EHCI_PID_OUT) { p_qhd->qtd_overlay.ping_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11 } } diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index 457adc1d3..87659701b 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -49,15 +49,14 @@ // TODO merge OHCI with EHCI enum { - EHCI_MAX_ITD = 4, + EHCI_MAX_ITD = 4, EHCI_MAX_SITD = 16 }; //--------------------------------------------------------------------+ // EHCI Data Structure //--------------------------------------------------------------------+ -enum -{ +enum { EHCI_QTYPE_ITD = 0 , EHCI_QTYPE_QHD , EHCI_QTYPE_SITD , @@ -65,8 +64,7 @@ enum }; /// EHCI PID -enum -{ +enum { EHCI_PID_OUT = 0 , EHCI_PID_IN , EHCI_PID_SETUP @@ -74,187 +72,182 @@ enum /// Link pointer typedef union { - uint32_t address; - struct { - uint32_t terminate : 1; - uint32_t type : 2; - }; -}ehci_link_t; + uint32_t address; + struct { + uint32_t terminate : 1; + uint32_t type : 2; + }; +} ehci_link_t; TU_VERIFY_STATIC( sizeof(ehci_link_t) == 4, "size is not correct" ); /// Queue Element Transfer Descriptor /// Qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with TU_ATTR_ALIGNED(32) -typedef struct -{ - // Word 0: Next QTD Pointer - ehci_link_t next; +typedef struct { + // Word 0 Next QTD Pointer + ehci_link_t next; - // Word 1: Alternate Next QTD Pointer (not used) - union{ - ehci_link_t alternate; - struct { - uint32_t : 5; - uint32_t used : 1; - uint32_t : 10; - uint32_t expected_bytes : 16; - }; - }; + // Word 1 Alternate Next QTD Pointer (not used) + union { + ehci_link_t alternate; + struct { + uint32_t : 5; + uint32_t used : 1; + uint32_t : 10; + uint32_t expected_bytes : 16; + }; + }; - // Word 2: qTQ Token - volatile uint32_t ping_err : 1 ; ///< For Highspeed: 0 Out, 1 Ping. Full/Slow used as error indicator - volatile uint32_t non_hs_split_state : 1 ; ///< Used by HC to track the state of split transaction - volatile uint32_t non_hs_missed_uframe : 1 ; ///< HC misses a complete split transaction - volatile uint32_t xact_err : 1 ; ///< Error (Timeout, CRC, Bad PID ... ) - volatile uint32_t babble_err : 1 ; ///< Babble detected, also set Halted bit to 1 - volatile uint32_t buffer_err : 1 ; ///< Data overrun/underrun error - volatile uint32_t halted : 1 ; ///< Serious error or STALL received - volatile uint32_t active : 1 ; ///< Start transfer, clear by HC when complete + // Word 2 qTQ Token + volatile uint32_t ping_err : 1; // For Highspeed: 0 Out, 1 Ping. Full/Slow used as error indicator + volatile uint32_t non_hs_split_state : 1; // Used by HC to track the state of split transaction + volatile uint32_t non_hs_missed_uframe : 1; // HC misses a complete split transaction + volatile uint32_t xact_err : 1; // Error (Timeout, CRC, Bad PID ... ) + volatile uint32_t babble_err : 1; // Babble detected, also set Halted bit to 1 + volatile uint32_t buffer_err : 1; // Data overrun/underrun error + volatile uint32_t halted : 1; // Serious error or STALL received + volatile uint32_t active : 1; // Start transfer, clear by HC when complete - uint32_t pid : 2 ; ///< 0: OUT, 1: IN, 2 Setup - volatile uint32_t err_count : 2 ; ///< Error Counter of consecutive errors - volatile uint32_t current_page : 3 ; ///< Index into the qTD buffer pointer list - uint32_t int_on_complete : 1 ; ///< Interrupt on complete - volatile uint32_t total_bytes : 15 ; ///< Transfer bytes, decreased during transaction - volatile uint32_t data_toggle : 1 ; ///< Data Toggle bit + uint32_t pid : 2; // 0: OUT, 1: IN, 2 Setup + volatile uint32_t err_count : 2; // Error Counter of consecutive errors + volatile uint32_t current_page : 3; // Index into the qTD buffer pointer list + uint32_t int_on_complete : 1; // Interrupt on complete + volatile uint32_t total_bytes : 15; // Transfer bytes, decreased during transaction + volatile uint32_t data_toggle : 1; // Data Toggle bit - - /// Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page - uint32_t buffer[5]; + // Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. + // The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page + uint32_t buffer[5]; } ehci_qtd_t; TU_VERIFY_STATIC( sizeof(ehci_qtd_t) == 32, "size is not correct" ); /// Queue Head -typedef struct TU_ATTR_ALIGNED(32) -{ - // Word 0: Next QHD - ehci_link_t next; +typedef struct TU_ATTR_ALIGNED(32) { + // Word 0 Next QHD + ehci_link_t next; - // Word 1: Endpoint Characteristics - uint32_t dev_addr : 7 ; ///< device address - uint32_t fl_inactive_next_xact : 1 ; ///< Only valid for Periodic with Full/Slow speed - uint32_t ep_number : 4 ; ///< EP number - uint32_t ep_speed : 2 ; ///< 0: Full, 1: Low, 2: High - uint32_t data_toggle_control : 1 ; ///< 0: use DT in qHD, 1: use DT in qTD - uint32_t head_list_flag : 1 ; ///< Head of the queue - uint32_t max_packet_size : 11 ; ///< Max packet size - uint32_t fl_ctrl_ep_flag : 1 ; ///< 1 if is Full/Low speed control endpoint - uint32_t nak_reload : 4 ; ///< Used by HC + // Word 1 Endpoint Characteristics + uint32_t dev_addr : 7; // device address + uint32_t fl_inactive_next_xact : 1; // Only valid for Periodic with Full/Slow speed + uint32_t ep_number : 4; // EP number + uint32_t ep_speed : 2; // Full (0), Low (1), High (2) + uint32_t data_toggle_control : 1; // 0 use DT in qHD, 1 use DT in qTD + uint32_t head_list_flag : 1; // Head of the queue + uint32_t max_packet_size : 11; // Max packet size + uint32_t fl_ctrl_ep_flag : 1; // 1 if is Full/Low speed control endpoint + uint32_t nak_reload : 4; // Used by HC - // Word 2: Endpoint Capabilities - uint32_t int_smask : 8 ; ///< Interrupt Schedule Mask - uint32_t fl_int_cmask : 8 ; ///< Split Completion Mask for Full/Slow speed - uint32_t fl_hub_addr : 7 ; ///< Hub Address for Full/Slow speed - uint32_t fl_hub_port : 7 ; ///< Hub Port for Full/Slow speed - uint32_t mult : 2 ; ///< Transaction per micro frame + // Word 2 Endpoint Capabilities + uint32_t int_smask : 8; // Interrupt Schedule Mask + uint32_t fl_int_cmask : 8; // Split Completion Mask for Full/Slow speed + uint32_t fl_hub_addr : 7; // Hub Address for Full/Slow speed + uint32_t fl_hub_port : 7; // Hub Port for Full/Slow speed + uint32_t mult : 2; // Transaction per micro frame - // Word 3: Current qTD Pointer - volatile uint32_t qtd_addr; + // Word 3 Current qTD Pointer + volatile uint32_t qtd_addr; - // Word 4-11: Transfer Overlay - volatile ehci_qtd_t qtd_overlay; + // Word 4-11 Transfer Overlay + volatile ehci_qtd_t qtd_overlay; - //--------------------------------------------------------------------+ - /// Due to the fact QHD is 32 bytes aligned but occupies only 48 bytes - /// thus there are 16 bytes padding free that we can make use of. //--------------------------------------------------------------------+ - uint8_t used; - uint8_t removing; // removed from asyn list, waiting for async advance - uint8_t pid; - uint8_t interval_ms; // polling interval in frames (or millisecond) + /// Due to the fact QHD is 32 bytes aligned but occupies only 48 bytes + /// thus there are 16 bytes padding free that we can make use of. + //--------------------------------------------------------------------+ + uint8_t used; + uint8_t removing;// removed from asyn list, waiting for async advance + uint8_t pid; + uint8_t interval_ms;// polling interval in frames (or millisecond) - uint8_t TU_RESERVED[4]; + uint8_t TU_RESERVED[4]; // Attached TD management, note usbh will only queue 1 TD per QHD. // buffer for dcache invalidate since td's buffer is modified by HC and finding initial buffer address is not trivial uint32_t attached_buffer; - ehci_qtd_t * volatile attached_qtd; + ehci_qtd_t *volatile attached_qtd; } ehci_qhd_t; - TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" ); /// Highspeed Isochronous Transfer Descriptor (section 3.3) typedef struct TU_ATTR_ALIGNED(32) { - // Word 0: Next Link Pointer - ehci_link_t next; + // Word 0: Next Link Pointer + ehci_link_t next; - // Word 1-8: iTD Transaction Status and Control List - struct { - // iTD Control - volatile uint32_t offset : 12 ; ///< This field is a value that is an offset, expressed in bytes, from the beginning of a buffer. - volatile uint32_t page_select : 3 ; ///< These bits are set by software to indicate which of the buffer page pointers the offset field in this slot should be concatenated to produce the starting memory address for this transaction. The valid range of values for this field is 0 to 6 - uint32_t int_on_complete : 1 ; ///< If this bit is set to a one, it specifies that when this transaction completes, the Host Controller should issue an interrupt at the next interrupt threshold - volatile uint32_t length : 12 ; ///< For an OUT, this field is the number of data bytes the host controller will send during the transaction. The host controller is not required to update this field to reflect the actual number of bytes transferred during the transfer - ///< For an IN, the initial value of the field is the number of bytes the host expects the endpoint to deliver. During the status update, the host controller writes back the number of bytes successfully received. The value in this register is the actual byte count - // iTD Status - volatile uint32_t error : 1 ; ///< Set to a one by the Host Controller during status update in the case where the host did not receive a valid response from the device (Timeout, CRC, Bad PID, etc.). This bit may only be set for isochronous IN transactions. - volatile uint32_t babble_err : 1 ; ///< Set to a 1 by the Host Controller during status update when a babble is detected during the transaction - volatile uint32_t buffer_err : 1 ; ///< Set to a 1 by the Host Controller during status update to indicate that the Host Controller is unable to keep up with the reception of incoming data (overrun) or is unable to supply data fast enough during transmission (underrun). - volatile uint32_t active : 1 ; ///< Set to 1 by software to enable the execution of an isochronous transaction by the Host Controller - } xact[8]; + // Word 1-8: iTD Transaction Status and Control List + struct { + // iTD Control + volatile uint32_t offset : 12; // offset in bytes, from the beginning of a buffer. + volatile uint32_t page_select : 3; // buffer page pointers the offset field in this slot should be concatenated to produce the starting memory address for this transaction. The valid range of values for this field is 0 to 6 + uint32_t int_on_complete : 1; // If this bit is set to a one, it specifies that when this transaction completes, the Host Controller should issue an interrupt at the next interrupt threshold + volatile uint32_t length : 12; // For an OUT, this field is the number of data bytes the host controller will send during the transaction. The host controller is not required to update this field to reflect the actual number of bytes transferred during the transfer + // For an IN, the initial value of the field is the number of bytes the host expects the endpoint to deliver. During the status update, the host controller writes back the number of bytes successfully received. The value in this register is the actual byte count + // iTD Status + volatile uint32_t error : 1; // Set to a one by the Host Controller during status update in the case where the host did not receive a valid response from the device (Timeout, CRC, Bad PID, etc.). This bit may only be set for isochronous IN transactions. + volatile uint32_t babble_err : 1; // Set to a 1 by the Host Controller during status update when a babble is detected during the transaction + volatile uint32_t buffer_err : 1; // Set to a 1 by the Host Controller during status update to indicate that the Host Controller is unable to keep up with the reception of incoming data (overrun) or is unable to supply data fast enough during transmission (underrun). + volatile uint32_t active : 1; // Set to 1 by software to enable the execution of an isochronous transaction by the Host Controller + } xact[8]; - // Word 9-15 Buffer Page Pointer List (Plus) - uint32_t BufferPointer[7]; + // Word 9-15 Buffer Page Pointer List (Plus) + uint32_t BufferPointer[7]; -// // FIXME: Store meta data into buffer pointer reserved for saving memory -// /*---------- HCD Area ----------*/ -// uint32_t used; -// uint32_t IhdIdx; -// uint32_t reserved[6]; + // FIXME: Store meta data into buffer pointer reserved for saving memory + //---------- HCD Area ---------- + // uint32_t used; + // uint32_t IhdIdx; + // uint32_t reserved[6]; } ehci_itd_t; - TU_VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" ); /// Split (Full-Speed) Isochronous Transfer Descriptor -typedef struct TU_ATTR_ALIGNED(32) -{ +typedef struct TU_ATTR_ALIGNED(32) { // Word 0: Next Link Pointer - ehci_link_t next; + ehci_link_t next; - // Word 1: siTD Endpoint Characteristics - uint32_t dev_addr : 7; ///< This field selects the specific device serving as the data source or sink. - uint32_t : 1; ///< reserved - uint32_t ep_number : 4; ///< This 4-bit field selects the particular endpoint number on the device serving as the data source or sink. - uint32_t : 4; ///< This field is reserved and should be set to zero. - uint32_t hub_addr : 7; ///< This field holds the device address of the transaction translators’ hub. - uint32_t : 1; ///< reserved - uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator. - uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT. + // Word 1: siTD Endpoint Characteristics + uint32_t dev_addr : 7; ///< This field selects the specific device serving as the data source or sink. + uint32_t : 1; ///< reserved + uint32_t ep_number : 4; ///< This 4-bit field selects the particular endpoint number on the device serving as the data source or sink. + uint32_t : 4; ///< This field is reserved and should be set to zero. + uint32_t hub_addr : 7; ///< This field holds the device address of the transaction translators’ hub. + uint32_t : 1; ///< reserved + uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator. + uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT. - // Word 2: Micro-frame Schedule Control - uint8_t int_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions - uint8_t fl_int_cmask; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute start-split transactions. - uint16_t reserved ; ///< reserved + // Word 2: Micro-frame Schedule Control + uint8_t int_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions + uint8_t fl_int_cmask; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute start-split transactions. + uint16_t reserved ; ///< reserved - // Word 3: siTD Transfer Status and Control - // Status [7:0] TODO identical to qTD Token'status --> refactor later - volatile uint32_t : 1 ; // reserved - volatile uint32_t split_state : 1 ; - volatile uint32_t missed_uframe : 1 ; - volatile uint32_t xact_err : 1 ; - volatile uint32_t babble_err : 1 ; - volatile uint32_t buffer_err : 1 ; - volatile uint32_t error : 1 ; - volatile uint32_t active : 1 ; - // Micro-frame Schedule Control - volatile uint32_t cmask_progress : 8 ; ///< This field is used by the host controller to record which split-completes have been executed. See Section 4.12.3.3.2 for behavioral requirements. - volatile uint32_t total_bytes : 10 ; ///< This field is initialized by software to the total number of bytes expected in this transfer. Maximum value is 1023 - volatile uint32_t : 4 ; ///< reserved - volatile uint32_t page_select : 1 ; ///< Used to indicate which data page pointer should be concatenated with the CurrentOffsetfield to construct a data buffer pointer - uint32_t int_on_complete : 1 ; ///< Do not interrupt when transaction is complete. 1 = Do interrupt when transaction is complete - uint32_t : 0 ; // padding to the end of current storage unit + // Word 3: siTD Transfer Status and Control + // Status [7:0] TODO identical to qTD Token'status --> refactor later + volatile uint32_t : 1 ; // reserved + volatile uint32_t split_state : 1 ; + volatile uint32_t missed_uframe : 1 ; + volatile uint32_t xact_err : 1 ; + volatile uint32_t babble_err : 1 ; + volatile uint32_t buffer_err : 1 ; + volatile uint32_t error : 1 ; + volatile uint32_t active : 1 ; + // Micro-frame Schedule Control + volatile uint32_t cmask_progress : 8 ; ///< This field is used by the host controller to record which split-completes have been executed. See Section 4.12.3.3.2 for behavioral requirements. + volatile uint32_t total_bytes : 10 ; ///< This field is initialized by software to the total number of bytes expected in this transfer. Maximum value is 1023 + volatile uint32_t : 4 ; ///< reserved + volatile uint32_t page_select : 1 ; ///< Used to indicate which data page pointer should be concatenated with the CurrentOffsetfield to construct a data buffer pointer + uint32_t int_on_complete : 1 ; ///< Do not interrupt when transaction is complete. 1 = Do interrupt when transaction is complete + uint32_t : 0 ; // padding to the end of current storage unit - /// Word 4-5: Buffer Pointer List - uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count + /// Word 4-5: Buffer Pointer List + uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count - /*---------- Word 6 ----------*/ - ehci_link_t back; + /*---------- Word 6 ----------*/ + ehci_link_t back; - /// SITD is 32-byte aligned but occupies only 28 --> 4 bytes for storing extra data - uint8_t used; - uint8_t ihd_idx; - uint8_t reserved2[2]; + /// SITD is 32-byte aligned but occupies only 28 --> 4 bytes for storing extra data + uint8_t used; + uint8_t ihd_idx; + uint8_t reserved2[2]; } ehci_sitd_t; TU_VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" ); @@ -315,8 +308,7 @@ enum { EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE }; -typedef volatile struct -{ +typedef volatile struct { union { uint32_t command; // 0x00 diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 662bb3a1f..8b89de66c 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -340,8 +340,8 @@ def test_host_device_info(board): ser.close() if len(data) == 0: assert False, 'No data from device' - lines = data.decode('utf-8', errors='ignore').splitlines() + enum_dev_sn = [] for l in lines: vid_pid_sn = re.search(r'ID ([0-9a-fA-F]+):([0-9a-fA-F]+) SN (\w+)', l) @@ -353,7 +353,6 @@ def test_host_device_info(board): failed_msg = f'Expected {declared_devs}, Enumerated {enum_dev_sn}' print('\n'.join(lines)) assert False, failed_msg - return 0 From e511d00f34b2832ae32ad0b2418a0878c7c4e7d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 Mar 2025 22:11:44 +0700 Subject: [PATCH 092/382] added hcd_edpt_close() stub for other ports --- src/portable/mentor/musb/hcd_musb.c | 5 ++ src/portable/nxp/khci/hcd_khci.c | 5 ++ src/portable/ohci/ohci.c | 6 ++- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 6 ++- src/portable/renesas/rusb2/hcd_rusb2.c | 5 ++ src/portable/synopsys/dwc2/hcd_dwc2.c | 5 ++ src/portable/template/hcd_template.c | 49 ++++++-------------- 7 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/portable/mentor/musb/hcd_musb.c b/src/portable/mentor/musb/hcd_musb.c index 1c0740193..811043d74 100644 --- a/src/portable/mentor/musb/hcd_musb.c +++ b/src/portable/mentor/musb/hcd_musb.c @@ -804,6 +804,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } +bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { + (void) rhport; (void) daddr; (void) ep_addr; + return false; // TODO not implemented yet +} + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { (void)rhport; diff --git a/src/portable/nxp/khci/hcd_khci.c b/src/portable/nxp/khci/hcd_khci.c index 056dbf40b..c3c901c5d 100644 --- a/src/portable/nxp/khci/hcd_khci.c +++ b/src/portable/nxp/khci/hcd_khci.c @@ -541,6 +541,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } +bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { + (void) rhport; (void) daddr; (void) ep_addr; + return false; // TODO not implemented yet +} + /* The address of buffer must be aligned to 4 byte boundary. And it must be at least 4 bytes long. * DMA writes data in 4 byte unit */ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index ce35eab70..672ad0443 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -451,7 +451,6 @@ static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ - bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { (void) rhport; @@ -486,6 +485,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } +bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { + (void) rhport; (void) daddr; (void) ep_addr; + return false; // TODO not implemented yet +} + bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { (void) rhport; diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 478c6e789..cd8c905d5 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -514,7 +514,6 @@ void hcd_int_disable(uint8_t rhport) //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ - bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { (void) rhport; @@ -535,6 +534,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } +bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { + (void) rhport; (void) daddr; (void) ep_addr; + return false; // TODO not implemented yet +} + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; diff --git a/src/portable/renesas/rusb2/hcd_rusb2.c b/src/portable/renesas/rusb2/hcd_rusb2.c index 4c81b05be..3e4b36981 100644 --- a/src/portable/renesas/rusb2/hcd_rusb2.c +++ b/src/portable/renesas/rusb2/hcd_rusb2.c @@ -718,6 +718,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } +bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { + (void) rhport; (void) daddr; (void) ep_addr; + return false; // TODO not implemented yet +} + bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { bool r; diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index b13479b02..f0cea529e 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -506,6 +506,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* return true; } +bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { + (void) rhport; (void) daddr; (void) ep_addr; + return false; // TODO not implemented yet +} + // clean up channel after part of transfer is done but the whole urb is not complete static void channel_xfer_out_wrapup(dwc2_regs_t* dwc2, uint8_t ch_id) { hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; diff --git a/src/portable/template/hcd_template.c b/src/portable/template/hcd_template.c index d8bca196f..1202c4ef4 100644 --- a/src/portable/template/hcd_template.c +++ b/src/portable/template/hcd_template.c @@ -36,24 +36,19 @@ // optional hcd configuration, called by tuh_configure() bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) { - (void) rhport; - (void) cfg_id; - (void) cfg_param; - + (void) rhport; (void) cfg_id; (void) cfg_param; return false; } // Initialize controller to host mode bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rhport; - (void) rh_init; + (void) rhport; (void) rh_init; return false; } // Interrupt Handler void hcd_int_handler(uint8_t rhport, bool in_isr) { - (void) rhport; - (void) in_isr; + (void) rhport; (void) in_isr; } // Enable USB interrupt @@ -69,7 +64,6 @@ void hcd_int_disable(uint8_t rhport) { // Get frame number (1ms) uint32_t hcd_frame_number(uint8_t rhport) { (void) rhport; - return 0; } @@ -80,7 +74,6 @@ uint32_t hcd_frame_number(uint8_t rhport) { // Get the current connect status of roothub port bool hcd_port_connect_status(uint8_t rhport) { (void) rhport; - return false; } @@ -98,14 +91,12 @@ void hcd_port_reset_end(uint8_t rhport) { // Get port link speed tusb_speed_t hcd_port_speed_get(uint8_t rhport) { (void) rhport; - return TUSB_SPEED_FULL; } // HCD closes all opened endpoints belong to this device void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { - (void) rhport; - (void) dev_addr; + (void) rhport; (void) dev_addr; } //--------------------------------------------------------------------+ @@ -114,49 +105,37 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { // Open an endpoint bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { - (void) rhport; - (void) dev_addr; - (void) ep_desc; - + (void) rhport; (void) dev_addr; (void) ep_desc; return false; } +bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) { + (void) rhport; (void) daddr; (void) ep_addr; + return false; // TODO not implemented yet +} + // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { - (void) rhport; - (void) dev_addr; - (void) ep_addr; - (void) buffer; - (void) buflen; - + (void) rhport; (void) dev_addr; (void) ep_addr; (void) buffer; (void) buflen; return false; } // Abort a queued transfer. Note: it can only abort transfer that has not been started // Return true if a queued transfer is aborted, false if there is no transfer to abort bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { - (void) rhport; - (void) dev_addr; - (void) ep_addr; - + (void) rhport; (void) dev_addr; (void) ep_addr; return false; } // Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { - (void) rhport; - (void) dev_addr; - (void) setup_packet; - + (void) rhport; (void) dev_addr; (void) setup_packet; return false; } // clear stall, data toggle is also reset to DATA0 bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { - (void) rhport; - (void) dev_addr; - (void) ep_addr; - + (void) rhport; (void) dev_addr; (void) ep_addr; return false; } From 5531de4f2c7e725b95f23083aad7d68d0d95b586 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 26 Mar 2025 23:20:00 +0700 Subject: [PATCH 093/382] add clion debugserver --- .idea/debugServers/rp2040.xml | 14 ++++++++++++++ .idea/debugServers/rp2350.xml | 14 ++++++++++++++ .idea/debugServers/rt1060.xml | 13 +++++++++++++ .idea/debugServers/rt1064.xml | 13 +++++++++++++ .idea/debugServers/sam21.xml | 13 +++++++++++++ .idea/debugServers/sam51.xml | 13 +++++++++++++ 6 files changed, 80 insertions(+) create mode 100644 .idea/debugServers/rp2040.xml create mode 100644 .idea/debugServers/rp2350.xml create mode 100644 .idea/debugServers/rt1060.xml create mode 100644 .idea/debugServers/rt1064.xml create mode 100644 .idea/debugServers/sam21.xml create mode 100644 .idea/debugServers/sam51.xml diff --git a/.idea/debugServers/rp2040.xml b/.idea/debugServers/rp2040.xml new file mode 100644 index 000000000..f451611f3 --- /dev/null +++ b/.idea/debugServers/rp2040.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/rp2350.xml b/.idea/debugServers/rp2350.xml new file mode 100644 index 000000000..5e092f3c4 --- /dev/null +++ b/.idea/debugServers/rp2350.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/rt1060.xml b/.idea/debugServers/rt1060.xml new file mode 100644 index 000000000..3325cc81f --- /dev/null +++ b/.idea/debugServers/rt1060.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/rt1064.xml b/.idea/debugServers/rt1064.xml new file mode 100644 index 000000000..4dc38ef63 --- /dev/null +++ b/.idea/debugServers/rt1064.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/sam21.xml b/.idea/debugServers/sam21.xml new file mode 100644 index 000000000..d8763b33b --- /dev/null +++ b/.idea/debugServers/sam21.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/sam51.xml b/.idea/debugServers/sam51.xml new file mode 100644 index 000000000..0d15ff856 --- /dev/null +++ b/.idea/debugServers/sam51.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file From 4787cd5f546eabad630fc5c22f37f67a076ac37e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Apr 2025 18:11:33 +0700 Subject: [PATCH 094/382] fix(hcd) hcd_edpt_open() return true if endpoint is already opened. --- examples/host/device_info/src/main.c | 31 +++++++++++++++-------- src/host/hcd.h | 1 + src/portable/analog/max3421/hcd_max3421.c | 2 +- src/portable/ehci/ehci.c | 4 ++- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c index ac4c46a11..e924a137b 100644 --- a/examples/host/device_info/src/main.c +++ b/examples/host/device_info/src/main.c @@ -124,13 +124,18 @@ void tuh_mount_cb(uint8_t daddr) { } printf("Device %u: ID %04x:%04x SN ", daddr, desc.device.idVendor, desc.device.idProduct); - xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, desc.serial, sizeof(desc.serial)); + + xfer_result = XFER_RESULT_FAILED; + if (desc.device.iSerialNumber != 0) { + xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, desc.serial, sizeof(desc.serial)); + } if (XFER_RESULT_SUCCESS != xfer_result) { uint16_t* serial = (uint16_t*)(uintptr_t) desc.serial; - serial[0] = 'n'; - serial[1] = '/'; - serial[2] = 'a'; - serial[3] = 0; + serial[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * 3 + 2)); + serial[1] = 'n'; + serial[2] = '/'; + serial[3] = 'a'; + serial[4] = 0; } print_utf16((uint16_t*)(uintptr_t) desc.serial, sizeof(desc.serial)/2); printf("\r\n"); @@ -150,16 +155,20 @@ void tuh_mount_cb(uint8_t daddr) { // Get String descriptor using Sync API printf(" iManufacturer %u ", desc.device.iManufacturer); - xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf)); - if (XFER_RESULT_SUCCESS == xfer_result) { - print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2); + if (desc.device.iManufacturer != 0) { + xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf)); + if (XFER_RESULT_SUCCESS == xfer_result) { + print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2); + } } printf("\r\n"); printf(" iProduct %u ", desc.device.iProduct); - xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf)); - if (XFER_RESULT_SUCCESS == xfer_result) { - print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2); + if (desc.device.iProduct != 0) { + xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf)); + if (XFER_RESULT_SUCCESS == xfer_result) { + print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2); + } } printf("\r\n"); diff --git a/src/host/hcd.h b/src/host/hcd.h index aa9e9cf3b..b20d96d54 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -163,6 +163,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); //--------------------------------------------------------------------+ // Open an endpoint +// return true if successfully opened or endpoint is currently opened bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * ep_desc); // Close an endpoint diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index 3fbf950a4..bb33200f2 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -611,7 +611,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e ep = &_hcd_data.ep[0]; }else { if (NULL != find_ep_not_addr0(daddr, ep_num, ep_dir)) { - return false; // endpoint already opened + return true; // already opened } ep = allocate_ep(); TU_ASSERT(ep); diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 292a352fb..7451f69a3 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -381,7 +381,9 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const if (ep_desc->bEndpointAddress == 0) { p_qhd = qhd_control(dev_addr); } else { - TU_VERIFY(NULL == qhd_get_from_addr(dev_addr, ep_desc->bEndpointAddress)); // ep not opened yet + if (NULL != qhd_get_from_addr(dev_addr, ep_desc->bEndpointAddress)) { + return true; // already opened + } p_qhd = qhd_find_free(); } TU_ASSERT(p_qhd); From 255ccf26ea29eb16be41f7715426c10be69b6e30 Mon Sep 17 00:00:00 2001 From: Maxime Vincent Date: Fri, 4 Apr 2025 14:21:20 +0200 Subject: [PATCH 095/382] dwc2/host: clear SOF flag in handle_sof_irq() --- src/portable/synopsys/dwc2/hcd_dwc2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index f0cea529e..7cbef05b7 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -1182,6 +1182,7 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) { static bool handle_sof_irq(uint8_t rhport, bool in_isr) { (void) in_isr; dwc2_regs_t* dwc2 = DWC2_REG(rhport); + dwc2->gintsts = GINTSTS_SOF; // Clear the SOF interrupt flag bool more_isr = false; From 1f2f92d97aea21345d0391caac05432ad06f4136 Mon Sep 17 00:00:00 2001 From: Radomir Dopieralski Date: Fri, 7 Mar 2025 12:20:33 +0100 Subject: [PATCH 096/382] Allow different port and mode for LED on ch32v boards While there is a define for the port, the clock enable is hardcoded for GPIOA, so setting a different port than GPIOA doesn't work. This fixes it by adding a define for enabling the port clock. It also adds a define for the pin mode, because not all boards have the LED connected in a way that open drain works with it. --- hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h | 2 ++ hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h | 2 ++ hw/bsp/ch32v20x/boards/nanoch32v203/board.h | 2 ++ hw/bsp/ch32v20x/family.c | 4 ++-- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h index 256958088..56f49205c 100644 --- a/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h +++ b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h @@ -13,6 +13,8 @@ extern "C" { #define LED_PORT GPIOA #define LED_PIN GPIO_Pin_0 #define LED_STATE_ON 0 +#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE) +#define LED_MODE GPIO_Mode_Out_OD #define UART_DEV USART1 #define UART_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE) diff --git a/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h index 827226d80..4a040e0df 100644 --- a/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h +++ b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h @@ -13,6 +13,8 @@ extern "C" { #define LED_PORT GPIOA #define LED_PIN GPIO_Pin_0 #define LED_STATE_ON 0 +#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE) +#define LED_MODE GPIO_Mode_Out_OD #define UART_DEV USART2 #define UART_CLOCK_EN() RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE) diff --git a/hw/bsp/ch32v20x/boards/nanoch32v203/board.h b/hw/bsp/ch32v20x/boards/nanoch32v203/board.h index f02fceced..63237861c 100644 --- a/hw/bsp/ch32v20x/boards/nanoch32v203/board.h +++ b/hw/bsp/ch32v20x/boards/nanoch32v203/board.h @@ -13,6 +13,8 @@ extern "C" { #define LED_PORT GPIOA #define LED_PIN GPIO_Pin_15 #define LED_STATE_ON 0 +#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE) +#define LED_MODE GPIO_Mode_Out_OD #define UART_DEV USART1 #define UART_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE) diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index 5f52d9447..21ed94b0a 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -96,11 +96,11 @@ void board_init(void) { SysTick_Config(SystemCoreClock / 1000); #endif - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); + LED_CLOCK_EN(); GPIO_InitTypeDef GPIO_InitStructure = { .GPIO_Pin = LED_PIN, - .GPIO_Mode = GPIO_Mode_Out_OD, + .GPIO_Mode = LED_MODE, .GPIO_Speed = GPIO_Speed_10MHz, }; GPIO_Init(LED_PORT, &GPIO_InitStructure); From 7d8433abab25734981f1b5eab3c5724a945df711 Mon Sep 17 00:00:00 2001 From: Maxime Vincent Date: Mon, 7 Apr 2025 11:36:02 +0200 Subject: [PATCH 097/382] dwc2/host: enable disconnect interrupt + handle it Signed-off-by: Maxime Vincent --- src/portable/synopsys/dwc2/hcd_dwc2.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 7cbef05b7..4c3d23b65 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -381,7 +381,7 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dwc2->hprt = HPRT_POWER; // turn on VBUS // Enable required interrupts - dwc2->gintmsk |= GINTSTS_OTGINT | GINTSTS_CONIDSTSCHNG | GINTSTS_HPRTINT | GINTSTS_HCINT; + dwc2->gintmsk |= GINTSTS_OTGINT | GINTSTS_CONIDSTSCHNG | GINTSTS_HPRTINT | GINTSTS_HCINT | GINTSTS_DISCINT; // NPTX can hold at least 2 packet, change interrupt level to half-empty uint32_t gahbcfg = dwc2->gahbcfg & ~GAHBCFG_TX_FIFO_EPMTY_LVL; @@ -1330,6 +1330,14 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { handle_channel_irq(rhport, in_isr); } + if (gintsts & GINTSTS_DISCINT) { + // Device disconnected + dwc2->gintsts = GINTSTS_DISCINT; + if (!(dwc2->hprt & HPRT_CONN_STATUS)) { + hcd_event_device_remove(rhport, in_isr); + } + } + #if CFG_TUH_DWC2_SLAVE_ENABLE // RxFIFO non-empty interrupt handling if (gintsts & GINTSTS_RXFLVL) { From 1be4171d2a00c2feed34e4e85582b4de3659e895 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 7 Apr 2025 23:30:10 +0200 Subject: [PATCH 098/382] Fix espressif build with presets. Signed-off-by: HiFiPhile --- hw/bsp/BoardPresets.json | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/hw/bsp/BoardPresets.json b/hw/bsp/BoardPresets.json index fee8f2c97..24da362da 100644 --- a/hw/bsp/BoardPresets.json +++ b/hw/bsp/BoardPresets.json @@ -12,21 +12,31 @@ "BOARD": "${presetName}" } }, + { + "name": "default single", + "hidden": true, + "description": "Configure preset for the ${presetName} board", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "BOARD": "${presetName}" + } + }, { "name": "adafruit_clue", "inherits": "default" }, { "name": "adafruit_feather_esp32_v2", - "inherits": "default" + "inherits": "default single" }, { "name": "adafruit_feather_esp32s2", - "inherits": "default" + "inherits": "default single" }, { "name": "adafruit_feather_esp32s3", - "inherits": "default" + "inherits": "default single" }, { "name": "adafruit_magtag_29gray", @@ -34,7 +44,7 @@ }, { "name": "adafruit_metro_esp32s2", - "inherits": "default" + "inherits": "default single" }, { "name": "apard32690", @@ -130,39 +140,39 @@ }, { "name": "espressif_addax_1", - "inherits": "default" + "inherits": "default single" }, { "name": "espressif_c3_devkitc", - "inherits": "default" + "inherits": "default single" }, { "name": "espressif_c6_devkitc", - "inherits": "default" + "inherits": "default single" }, { "name": "espressif_kaluga_1", - "inherits": "default" + "inherits": "default single" }, { "name": "espressif_p4_function_ev", - "inherits": "default" + "inherits": "default single" }, { "name": "espressif_s2_devkitc", - "inherits": "default" + "inherits": "default single" }, { "name": "espressif_s3_devkitc", - "inherits": "default" + "inherits": "default single" }, { "name": "espressif_s3_devkitm", - "inherits": "default" + "inherits": "default single" }, { "name": "espressif_saola_1", - "inherits": "default" + "inherits": "default single" }, { "name": "f1c100s", From 6607b76c761a3a64a7c43ceba27ae42cdb368e52 Mon Sep 17 00:00:00 2001 From: Maxime Vincent Date: Tue, 8 Apr 2025 14:34:11 +0200 Subject: [PATCH 099/382] dwc2/host: remove hcd_event_device_remove() call from handle_hptr_irq to prevent double removal Signed-off-by: Maxime Vincent --- src/portable/synopsys/dwc2/hcd_dwc2.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 4c3d23b65..4aa42759f 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -1266,8 +1266,6 @@ static void handle_hprt_irq(uint8_t rhport, bool in_isr) { if (hprt_bm.conn_status) { hcd_event_device_attach(rhport, in_isr); - } else { - hcd_event_device_remove(rhport, in_isr); } } From 084c0802c310c836e0c3e972b724a5a0d17057ba Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 9 Apr 2025 01:31:16 +0200 Subject: [PATCH 100/382] dwc2: refactor bitfields. Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/dcd_dwc2.c | 86 +-- src/portable/synopsys/dwc2/dwc2_common.c | 16 +- src/portable/synopsys/dwc2/dwc2_type.h | 945 +++++++++++------------ src/portable/synopsys/dwc2/hcd_dwc2.c | 202 +++-- 4 files changed, 643 insertions(+), 606 deletions(-) diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index c461d9a79..83ebc18cb 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -44,7 +44,7 @@ #if TU_CHECK_MCU(OPT_MCU_GD32VF103) #define DWC2_EP_COUNT(_dwc2) DWC2_EP_MAX #else - #define DWC2_EP_COUNT(_dwc2) ((_dwc2)->ghwcfg2_bm.num_dev_ep + 1) + #define DWC2_EP_COUNT(_dwc2) ({const dwc2_ghwcfg2_t ghwcfg2 = {.value = (_dwc2)->ghwcfg2}; ghwcfg2.num_dev_ep + 1;}) #endif //--------------------------------------------------------------------+ @@ -102,7 +102,8 @@ bool dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) { TU_ATTR_ALWAYS_INLINE static inline bool dma_device_enabled(const dwc2_regs_t* dwc2) { (void) dwc2; // Internal DMA only - return CFG_TUD_DWC2_DMA_ENABLE && dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA; + const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; + return CFG_TUD_DWC2_DMA_ENABLE && ghwcfg2.arch == GHWCFG2_ARCH_INTERNAL_DMA; } static void dma_setup_prepare(uint8_t rhport) { @@ -250,20 +251,15 @@ static void edpt_activate(uint8_t rhport, const tusb_desc_endpoint_t* p_endpoint xfer->interval = p_endpoint_desc->bInterval; // Endpoint control - union { - uint32_t value; - dwc2_depctl_t bm; - } depctl; - depctl.value = 0; - - depctl.bm.mps = xfer->max_size; - depctl.bm.active = 1; - depctl.bm.type = p_endpoint_desc->bmAttributes.xfer; + dwc2_depctl_t depctl = {.value = 0}; + depctl.mps = xfer->max_size; + depctl.active = 1; + depctl.type = p_endpoint_desc->bmAttributes.xfer; if (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) { - depctl.bm.set_data0_iso_even = 1; + depctl.set_data0_iso_even = 1; } if (dir == TUSB_DIR_IN) { - depctl.bm.tx_fifo_num = epnum; + depctl.tx_fifo_num = epnum; } dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; @@ -343,31 +339,22 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin } // transfer size: A full OUT transfer (multiple packets, possibly) triggers XFRC. - union { - uint32_t value; - dwc2_ep_tsize_t bm; - } deptsiz; - deptsiz.value = 0; - deptsiz.bm.xfer_size = total_bytes; - deptsiz.bm.packet_count = num_packets; - + dwc2_ep_tsize_t deptsiz = {.value = 0}; + deptsiz.xfer_size = total_bytes; + deptsiz.packet_count = num_packets; dep->tsiz = deptsiz.value; // control - union { - dwc2_depctl_t bm; - uint32_t value; - } depctl; - depctl.value = dep->ctl; - - depctl.bm.clear_nak = 1; - depctl.bm.enable = 1; - if (depctl.bm.type == DEPCTL_EPTYPE_ISOCHRONOUS && xfer->interval == 1) { - const uint32_t odd_now = (dwc2->dsts_bm.frame_number & 1u); + dwc2_depctl_t depctl = {.value = dep->ctl}; + depctl.clear_nak = 1; + depctl.enable = 1; + if (depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS && xfer->interval == 1) { + const dwc2_dsts_t dsts = {.value = dwc2->dsts}; + const uint32_t odd_now = dsts.frame_number & 1u; if (odd_now) { - depctl.bm.set_data0_iso_even = 1; + depctl.set_data0_iso_even = 1; } else { - depctl.bm.set_data1_iso_odd = 1; + depctl.set_data1_iso_odd = 1; } } @@ -410,7 +397,8 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required // when using with some PHYs such as USB334x (USB3341, USB3343, USB3346, USB3347) - if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) { + const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; + if (ghwcfg2.hs_phy_type == GHWCFG2_HSPHY_ULPI) { dcfg |= DCFG_XCVRDLY; } } else { @@ -671,7 +659,9 @@ static void handle_bus_reset(uint8_t rhport) { dfifo_device_init(rhport); // 5. Reset device address - dwc2->dcfg_bm.address = 0; + dwc2_dcfg_t dcfg = {.value = dwc2->dcfg}; + dcfg.address = 0; + dwc2->dcfg = dcfg.value; // Fixed both control EP0 size to 64 bytes dwc2->epin[0].ctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); @@ -691,8 +681,9 @@ static void handle_bus_reset(uint8_t rhport) { static void handle_enum_done(uint8_t rhport) { dwc2_regs_t *dwc2 = DWC2_REG(rhport); + const dwc2_dsts_t dsts = {.value = dwc2->dsts}; tusb_speed_t speed; - switch (dwc2->dsts_bm.enum_speed) { + switch (dsts.enum_speed) { case DCFG_SPEED_HIGH: speed = TUSB_SPEED_HIGH; break; @@ -737,12 +728,12 @@ static void handle_rxflvl_irq(uint8_t rhport) { const volatile uint32_t* rx_fifo = dwc2->fifo[0]; // Pop control word off FIFO - const dwc2_grxstsp_t grxstsp_bm = dwc2->grxstsp_bm; - const uint8_t epnum = grxstsp_bm.ep_ch_num; + const dwc2_grxstsp_t grxstsp = {.value = dwc2->grxstsp}; + const uint8_t epnum = grxstsp.ep_ch_num; dwc2_dep_t* epout = &dwc2->epout[epnum]; - switch (grxstsp_bm.packet_status) { + switch (grxstsp.packet_status) { case GRXSTS_PKTSTS_GLOBAL_OUT_NAK: // Global OUT NAK: do nothing break; @@ -764,7 +755,7 @@ static void handle_rxflvl_irq(uint8_t rhport) { case GRXSTS_PKTSTS_RX_DATA: { // Out packet received - const uint16_t byte_count = grxstsp_bm.byte_count; + const uint16_t byte_count = grxstsp.byte_count; xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); if (byte_count) { @@ -778,7 +769,8 @@ static void handle_rxflvl_irq(uint8_t rhport) { // short packet, minus remaining bytes (xfer_size) if (byte_count < xfer->max_size) { - xfer->total_len -= epout->tsiz_bm.xfer_size; + const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz}; + xfer->total_len -= tsiz.xfer_size; if (epnum == 0) { xfer->total_len -= _dcd_data.ep0_pending[TUSB_DIR_OUT]; _dcd_data.ep0_pending[TUSB_DIR_OUT] = 0; @@ -840,11 +832,13 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep // - 64 bytes or // - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL) if (diepint_bm.txfifo_empty && (dwc2->diepempmsk & (1 << epnum))) { - const uint16_t remain_packets = epin->tsiz_bm.packet_count; + dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; + const uint16_t remain_packets = tsiz.packet_count; // Process every single packet (only whole packets can be written to fifo) for (uint16_t i = 0; i < remain_packets; i++) { - const uint16_t remain_bytes = (uint16_t) epin->tsiz_bm.xfer_size; + tsiz.value = epin->tsiz; + const uint16_t remain_bytes = (uint16_t) tsiz.xfer_size; const uint16_t xact_bytes = tu_min16(remain_bytes, xfer->max_size); // Check if dtxfsts has enough space available @@ -863,7 +857,8 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep } // Turn off TXFE if all bytes are written. - if (epin->tsiz_bm.xfer_size == 0) { + tsiz.value = epin->tsiz; + if (tsiz.xfer_size == 0) { dwc2->diepempmsk &= ~(1 << epnum); } } @@ -894,7 +889,8 @@ static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepi xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); // determine actual received bytes - const uint16_t remain = epout->tsiz_bm.xfer_size; + const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz}; + const uint16_t remain = tsiz.xfer_size; xfer->total_len -= remain; // this is ZLP, so prepare EP0 for next setup diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index f80ae9acb..989a833ff 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -88,11 +88,13 @@ static void phy_fs_init(dwc2_regs_t* dwc2) { static void phy_hs_init(dwc2_regs_t* dwc2) { uint32_t gusbcfg = dwc2->gusbcfg; + const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; + const dwc2_ghwcfg4_t ghwcfg4 = {.value = dwc2->ghwcfg4}; // De-select FS PHY gusbcfg &= ~GUSBCFG_PHYSEL; - if (dwc2->ghwcfg2_bm.hs_phy_type == GHWCFG2_HSPHY_ULPI) { + if (ghwcfg2.hs_phy_type == GHWCFG2_HSPHY_ULPI) { TU_LOG(DWC2_COMMON_DEBUG, "Highspeed ULPI PHY init\r\n"); // Select ULPI PHY (external) @@ -116,7 +118,7 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { gusbcfg &= ~GUSBCFG_ULPI_UTMI_SEL; // Set 16-bit interface if supported - if (dwc2->ghwcfg4_bm.phy_data_width) { + if (ghwcfg4.phy_data_width) { gusbcfg |= GUSBCFG_PHYIF16; // 16 bit } else { gusbcfg &= ~GUSBCFG_PHYIF16; // 8 bit @@ -127,7 +129,7 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { dwc2->gusbcfg = gusbcfg; // mcu specific phy init - dwc2_phy_init(dwc2, dwc2->ghwcfg2_bm.hs_phy_type); + dwc2_phy_init(dwc2, ghwcfg2.hs_phy_type); // Reset core after selecting PHY reset_core(dwc2); @@ -136,11 +138,11 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { // - 9 if using 8-bit PHY interface // - 5 if using 16-bit PHY interface gusbcfg &= ~GUSBCFG_TRDT_Msk; - gusbcfg |= (dwc2->ghwcfg4_bm.phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos; + gusbcfg |= (ghwcfg4.phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos; dwc2->gusbcfg = gusbcfg; // MCU specific PHY update post reset - dwc2_phy_update(dwc2, dwc2->ghwcfg2_bm.hs_phy_type); + dwc2_phy_update(dwc2, ghwcfg2.hs_phy_type); } static bool check_dwc2(dwc2_regs_t* dwc2) { @@ -171,7 +173,7 @@ static bool check_dwc2(dwc2_regs_t* dwc2) { //-------------------------------------------------------------------- bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role) { (void)dwc2; - + const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; #if CFG_TUD_ENABLED if (role == TUSB_ROLE_DEVICE && !TUD_OPT_HIGH_SPEED) { return false; @@ -183,7 +185,7 @@ bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role) { } #endif - return dwc2->ghwcfg2_bm.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED; + return ghwcfg2.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED; } /* dwc2 has several PHYs option diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 812096759..5ecf9d487 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -184,415 +184,470 @@ enum { //-------------------------------------------------------------------- // Common Register Bitfield //-------------------------------------------------------------------- -typedef struct TU_ATTR_PACKED { - uint32_t ses_req_scs : 1; // 0 Session request success - uint32_t ses_req : 1; // 1 Session request - uint32_t vbval_ov_en : 1; // 2 VBUS valid override enable - uint32_t vbval_ov_val : 1; // 3 VBUS valid override value - uint32_t aval_ov_en : 1; // 4 A-peripheral session valid override enable - uint32_t aval_ov_al : 1; // 5 A-peripheral session valid override value - uint32_t bval_ov_en : 1; // 6 B-peripheral session valid override enable - uint32_t bval_ov_val : 1; // 7 B-peripheral session valid override value - uint32_t hng_scs : 1; // 8 Host negotiation success - uint32_t hnp_rq : 1; // 9 HNP (host negotiation protocol) request - uint32_t host_set_hnp_en : 1; // 10 Host set HNP enable - uint32_t dev_hnp_en : 1; // 11 Device HNP enabled - uint32_t embedded_host_en : 1; // 12 Embedded host enable - uint32_t rsv13_14 : 2; // 13.14 Reserved - uint32_t dbnc_filter_bypass : 1; // 15 Debounce filter bypass - uint32_t cid_status : 1; // 16 Connector ID status - uint32_t dbnc_done : 1; // 17 Debounce done - uint32_t ases_valid : 1; // 18 A-session valid - uint32_t bses_valid : 1; // 19 B-session valid - uint32_t otg_ver : 1; // 20 OTG version 0: v1.3, 1: v2.0 - uint32_t current_mode : 1; // 21 Current mode of operation. Only from v3.00a - uint32_t mult_val_id_bc : 5; // 22..26 Multi-valued input pin ID battery charger - uint32_t chirp_en : 1; // 27 Chirp detection enable - uint32_t rsv28_30 : 3; // 28.30: Reserved - uint32_t test_mode_corr_eusb2 : 1; // 31 Test mode control for eUSB2 PHY +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t ses_req_scs : 1; // 0 Session request success + uint32_t ses_req : 1; // 1 Session request + uint32_t vbval_ov_en : 1; // 2 VBUS valid override enable + uint32_t vbval_ov_val : 1; // 3 VBUS valid override value + uint32_t aval_ov_en : 1; // 4 A-peripheral session valid override enable + uint32_t aval_ov_al : 1; // 5 A-peripheral session valid override value + uint32_t bval_ov_en : 1; // 6 B-peripheral session valid override enable + uint32_t bval_ov_val : 1; // 7 B-peripheral session valid override value + uint32_t hng_scs : 1; // 8 Host negotiation success + uint32_t hnp_rq : 1; // 9 HNP (host negotiation protocol) request + uint32_t host_set_hnp_en : 1; // 10 Host set HNP enable + uint32_t dev_hnp_en : 1; // 11 Device HNP enabled + uint32_t embedded_host_en : 1; // 12 Embedded host enable + uint32_t rsv13_14 : 2; // 13.14 Reserved + uint32_t dbnc_filter_bypass : 1; // 15 Debounce filter bypass + uint32_t cid_status : 1; // 16 Connector ID status + uint32_t dbnc_done : 1; // 17 Debounce done + uint32_t ases_valid : 1; // 18 A-session valid + uint32_t bses_valid : 1; // 19 B-session valid + uint32_t otg_ver : 1; // 20 OTG version 0: v1.3, 1: v2.0 + uint32_t current_mode : 1; // 21 Current mode of operation. Only from v3.00a + uint32_t mult_val_id_bc : 5; // 22..26 Multi-valued input pin ID battery charger + uint32_t chirp_en : 1; // 27 Chirp detection enable + uint32_t rsv28_30 : 3; // 28.30: Reserved + uint32_t test_mode_corr_eusb2 : 1; // 31 Test mode control for eUSB2 PHY + }; } dwc2_gotgctl_t; TU_VERIFY_STATIC(sizeof(dwc2_gotgctl_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t rsv0_1 : 2; // 0..1 Reserved - uint32_t ses_end_det : 1; // 2 Session end detected - uint32_t rsv3_7 : 5; // 3..7 Reserved - uint32_t srs_status_change : 1; // 8 Session request success status change - uint32_t hns_status_change : 1; // 9 Host negotiation success status change - uint32_t rsv10_16 : 7; // 10..16 Reserved - uint32_t hng_det : 1; // 17 Host negotiation detected - uint32_t adev_timeout_change : 1; // 18 A-device timeout change - uint32_t dbnc_done : 1; // 19 Debounce done - uint32_t mult_val_lp_change : 1; // 20 Multi-valued input pin change - uint32_t rsv21_31 :11; // 21..31 Reserved +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t rsv0_1 : 2; // 0..1 Reserved + uint32_t ses_end_det : 1; // 2 Session end detected + uint32_t rsv3_7 : 5; // 3..7 Reserved + uint32_t srs_status_change : 1; // 8 Session request success status change + uint32_t hns_status_change : 1; // 9 Host negotiation success status change + uint32_t rsv10_16 : 7; // 10..16 Reserved + uint32_t hng_det : 1; // 17 Host negotiation detected + uint32_t adev_timeout_change : 1; // 18 A-device timeout change + uint32_t dbnc_done : 1; // 19 Debounce done + uint32_t mult_val_lp_change : 1; // 20 Multi-valued input pin change + uint32_t rsv21_31 :11; // 21..31 Reserved + }; } dwc2_gotgint_t; TU_VERIFY_STATIC(sizeof(dwc2_gotgint_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t gintmask : 1; // 0 Global interrupt mask - uint32_t hbst_len : 4; // 1..4 Burst length/type - uint32_t dma_en : 1; // 5 DMA enable - uint32_t rsv6 : 1; // 6 Reserved - uint32_t nptxf_empty_lvl : 1; // 7 Non-periodic Tx FIFO empty level - uint32_t ptxf_empty_lvl : 1; // 8 Periodic Tx FIFO empty level - uint32_t rsv9_20 : 12; // 9.20: Reserved - uint32_t remote_mem_support : 1; // 21 Remote memory support - uint32_t notify_all_dma_write : 1; // 22 Notify all DMA writes - uint32_t ahb_single : 1; // 23 AHB single - uint32_t inv_desc_endian : 1; // 24 Inverse descriptor endian - uint32_t rsv25_31 : 7; // 25..31 Reserved +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t gintmask : 1; // 0 Global interrupt mask + uint32_t hbst_len : 4; // 1..4 Burst length/type + uint32_t dma_en : 1; // 5 DMA enable + uint32_t rsv6 : 1; // 6 Reserved + uint32_t nptxf_empty_lvl : 1; // 7 Non-periodic Tx FIFO empty level + uint32_t ptxf_empty_lvl : 1; // 8 Periodic Tx FIFO empty level + uint32_t rsv9_20 : 12; // 9.20: Reserved + uint32_t remote_mem_support : 1; // 21 Remote memory support + uint32_t notify_all_dma_write : 1; // 22 Notify all DMA writes + uint32_t ahb_single : 1; // 23 AHB single + uint32_t inv_desc_endian : 1; // 24 Inverse descriptor endian + uint32_t rsv25_31 : 7; // 25..31 Reserved + }; } dwc2_gahbcfg_t; TU_VERIFY_STATIC(sizeof(dwc2_gahbcfg_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t timeout_cal : 3; /* 0..2 Timeout calibration. - The USB standard timeout value for high-speed operation is 736 to 816 (inclusive) bit times. The USB standard - timeout value for full- speed operation is 16 to 18 (inclusive) bit times. The application must program this field - based on the speed of enumeration. The number of bit times added per PHY clock are as follows: - - High-speed: PHY clock One 30-MHz = 16 bit times, One 60-MHz = 8 bit times - - Full-speed: PHY clock One 30-MHz = 0.4 bit times, One 60-MHz = 0.2 bit times, One 48-MHz = 0.25 bit times */ - uint32_t phy_if16 : 1; // 3 PHY interface. 0: 8 bits, 1: 16 bits - uint32_t ulpi_utmi_sel : 1; // 4 ULPI/UTMI select. 0: UTMI+, 1: ULPI - uint32_t fs_intf_sel : 1; // 5 Fullspeed serial interface select. 0: 6-pin, 1: 3-pin - uint32_t phy_sel : 1; // 6 HS/FS PHY selection. 0: HS UTMI+ or ULPI, 1: FS serial transceiver - uint32_t ddr_sel : 1; // 7 ULPI DDR select. 0: Single data rate 8-bit, 1: Double data rate 4-bit - uint32_t srp_capable : 1; // 8 SRP-capable - uint32_t hnp_capable : 1; // 9 HNP-capable - uint32_t turnaround_time : 4; // 10..13 Turnaround time. 9: 8-bit UTMI+, 5: 16-bit UTMI+ - uint32_t rsv14 : 1; // 14 Reserved - uint32_t phy_low_power_clk_sel : 1; /* 15 PHY low-power clock select either 480-MHz or 48-MHz (low-power) PHY mode. - In FS/LS modes, the PHY can usually operate on a 48-MHz clock to save power. This bit is valid only for UTMI+ PHYs. - - 0: 480 Mhz internal PLL: the UTMI interface operates at either 60 MHz (8 bit) or 30 MHz (16-bit) - - 1 48 Mhz external clock: the UTMI interface operates at 48 MHz in FS mode and at either 48 or 6 MHz in LS mode */ - uint32_t otg_i2c_sel : 1; // 16 OTG I2C interface select. 0: UTMI-FS, 1: I2C for OTG signals - uint32_t ulpi_fsls : 1; /* 17 ULPI FS/LS select. 0: ULPI, 1: ULPI FS/LS. - valid only when the FS serial transceiver is selected on the ULPI PHY. */ - uint32_t ulpi_auto_resume : 1; // 18 ULPI Auto-resume - uint32_t ulpi_clk_sus_m : 1; // 19 ULPI Clock SuspendM - uint32_t ulpi_ext_vbus_drv : 1; // 20 ULPI External VBUS Drive - uint32_t ulpi_int_vbus_indicator : 1; // 21 ULPI Internal VBUS Indicator - uint32_t term_sel_dl_pulse : 1; // 22 TermSel DLine pulsing - uint32_t indicator_complement : 1; // 23 Indicator complement - uint32_t indicator_pass_through : 1; // 24 Indicator pass through - uint32_t ulpi_if_protect_disable : 1; // 25 ULPI interface protect disable - uint32_t ic_usb_capable : 1; // 26 IC_USB Capable - uint32_t ic_usb_traf_ctl : 1; // 27 IC_USB Traffic Control - uint32_t tx_end_delay : 1; // 28 TX end delay - uint32_t force_host_mode : 1; // 29 Force host mode - uint32_t force_dev_mode : 1; // 30 Force device mode - uint32_t corrupt_tx_pkt : 1; // 31 Corrupt Tx packet. 0: normal, 1: debug +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t timeout_cal : 3; /* 0..2 Timeout calibration. + The USB standard timeout value for high-speed operation is 736 to 816 (inclusive) bit times. The USB standard + timeout value for full- speed operation is 16 to 18 (inclusive) bit times. The application must program this field + based on the speed of enumeration. The number of bit times added per PHY clock are as follows: + - High-speed: PHY clock One 30-MHz = 16 bit times, One 60-MHz = 8 bit times + - Full-speed: PHY clock One 30-MHz = 0.4 bit times, One 60-MHz = 0.2 bit times, One 48-MHz = 0.25 bit times */ + uint32_t phy_if16 : 1; // 3 PHY interface. 0: 8 bits, 1: 16 bits + uint32_t ulpi_utmi_sel : 1; // 4 ULPI/UTMI select. 0: UTMI+, 1: ULPI + uint32_t fs_intf_sel : 1; // 5 Fullspeed serial interface select. 0: 6-pin, 1: 3-pin + uint32_t phy_sel : 1; // 6 HS/FS PHY selection. 0: HS UTMI+ or ULPI, 1: FS serial transceiver + uint32_t ddr_sel : 1; // 7 ULPI DDR select. 0: Single data rate 8-bit, 1: Double data rate 4-bit + uint32_t srp_capable : 1; // 8 SRP-capable + uint32_t hnp_capable : 1; // 9 HNP-capable + uint32_t turnaround_time : 4; // 10..13 Turnaround time. 9: 8-bit UTMI+, 5: 16-bit UTMI+ + uint32_t rsv14 : 1; // 14 Reserved + uint32_t phy_low_power_clk_sel : 1; /* 15 PHY low-power clock select either 480-MHz or 48-MHz (low-power) PHY mode. + In FS/LS modes, the PHY can usually operate on a 48-MHz clock to save power. This bit is valid only for UTMI+ PHYs. + - 0: 480 Mhz internal PLL: the UTMI interface operates at either 60 MHz (8 bit) or 30 MHz (16-bit) + - 1 48 Mhz external clock: the UTMI interface operates at 48 MHz in FS mode and at either 48 or 6 MHz in LS mode */ + uint32_t otg_i2c_sel : 1; // 16 OTG I2C interface select. 0: UTMI-FS, 1: I2C for OTG signals + uint32_t ulpi_fsls : 1; /* 17 ULPI FS/LS select. 0: ULPI, 1: ULPI FS/LS. + valid only when the FS serial transceiver is selected on the ULPI PHY. */ + uint32_t ulpi_auto_resume : 1; // 18 ULPI Auto-resume + uint32_t ulpi_clk_sus_m : 1; // 19 ULPI Clock SuspendM + uint32_t ulpi_ext_vbus_drv : 1; // 20 ULPI External VBUS Drive + uint32_t ulpi_int_vbus_indicator : 1; // 21 ULPI Internal VBUS Indicator + uint32_t term_sel_dl_pulse : 1; // 22 TermSel DLine pulsing + uint32_t indicator_complement : 1; // 23 Indicator complement + uint32_t indicator_pass_through : 1; // 24 Indicator pass through + uint32_t ulpi_if_protect_disable : 1; // 25 ULPI interface protect disable + uint32_t ic_usb_capable : 1; // 26 IC_USB Capable + uint32_t ic_usb_traf_ctl : 1; // 27 IC_USB Traffic Control + uint32_t tx_end_delay : 1; // 28 TX end delay + uint32_t force_host_mode : 1; // 29 Force host mode + uint32_t force_dev_mode : 1; // 30 Force device mode + uint32_t corrupt_tx_pkt : 1; // 31 Corrupt Tx packet. 0: normal, 1: debug + }; } dwc2_gusbcfg_t; TU_VERIFY_STATIC(sizeof(dwc2_gusbcfg_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t core_soft_rst : 1; // 0 Core Soft Reset - uint32_t piufs_soft_rst : 1; // 1 PIU FS Dedicated Controller Soft Reset - uint32_t frame_counter_rst : 1; // 2 Frame Counter Reset (host) - uint32_t intoken_q_flush : 1; // 3 IN Token Queue Flush - uint32_t rx_fifo_flush : 1; // 4 RX FIFO Flush - uint32_t tx_fifo_flush : 1; // 5 TX FIFO Flush - uint32_t tx_fifo_num : 5; // 6..10 TX FIFO Number - uint32_t rsv11_28 :18; // 11..28 Reserved - uint32_t core_soft_rst_done : 1; // 29 Core Soft Reset Done, from v4.20a - uint32_t dma_req : 1; // 30 DMA Request - uint32_t ahb_idle : 1; // 31 AHB Idle +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t core_soft_rst : 1; // 0 Core Soft Reset + uint32_t piufs_soft_rst : 1; // 1 PIU FS Dedicated Controller Soft Reset + uint32_t frame_counter_rst : 1; // 2 Frame Counter Reset (host) + uint32_t intoken_q_flush : 1; // 3 IN Token Queue Flush + uint32_t rx_fifo_flush : 1; // 4 RX FIFO Flush + uint32_t tx_fifo_flush : 1; // 5 TX FIFO Flush + uint32_t tx_fifo_num : 5; // 6..10 TX FIFO Number + uint32_t rsv11_28 :18; // 11..28 Reserved + uint32_t core_soft_rst_done : 1; // 29 Core Soft Reset Done, from v4.20a + uint32_t dma_req : 1; // 30 DMA Request + uint32_t ahb_idle : 1; // 31 AHB Idle + }; } dwc2_grstctl_t; TU_VERIFY_STATIC(sizeof(dwc2_grstctl_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t ep_ch_num : 4; // 0..3 Endpoint/Channel Number - uint32_t byte_count :11; // 4..14 Byte Count - uint32_t dpid : 2; // 15..16 Data PID - uint32_t packet_status : 4; // 17..20 Packet Status - uint32_t frame_number : 4; // 21..24 Frame Number - uint32_t rsv25_31 : 7; // 25..31 Reserved +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t ep_ch_num : 4; // 0..3 Endpoint/Channel Number + uint32_t byte_count :11; // 4..14 Byte Count + uint32_t dpid : 2; // 15..16 Data PID + uint32_t packet_status : 4; // 17..20 Packet Status + uint32_t frame_number : 4; // 21..24 Frame Number + uint32_t rsv25_31 : 7; // 25..31 Reserved + }; } dwc2_grxstsp_t; TU_VERIFY_STATIC(sizeof(dwc2_grxstsp_t) == 4, "incorrect size"); -// Hardware Configuration -typedef struct TU_ATTR_PACKED { - uint32_t op_mode : 3; // 0..2 HNP/SRP Host/Device/OTG mode - uint32_t arch : 2; // 3..4 Slave/External/Internal DMA - uint32_t single_point : 1; // 5 0: support hub and split | 1: no hub, no split - uint32_t hs_phy_type : 2; // 6..7 0: not supported | 1: UTMI+ | 2: ULPI | 3: UTMI+ and ULPI - uint32_t fs_phy_type : 2; // 8..9 0: not supported | 1: dedicated | 2: UTMI+ | 3: ULPI - uint32_t num_dev_ep : 4; // 10..13 Number of device endpoints (excluding EP0) - uint32_t num_host_ch : 4; // 14..17 Number of host channel (excluding control) - uint32_t period_channel_support : 1; // 18 Support Periodic OUT Host Channel - uint32_t enable_dynamic_fifo : 1; // 19 Dynamic FIFO Sizing Enabled - uint32_t mul_proc_intrpt : 1; // 20 Multi-Processor Interrupt enabled (OTG_MULTI_PROC_INTRPT) - uint32_t reserved21 : 1; // 21 reserved - uint32_t nptx_q_depth : 2; // 22..23 Non-periodic request queue depth: 0 = 2. 1 = 4, 2 = 8 - uint32_t ptx_q_depth : 2; // 24..25 Host periodic request queue depth: 0 = 2. 1 = 4, 2 = 8 - uint32_t token_q_depth : 5; // 26..30 Device IN token sequence learning queue depth: 0-30 - uint32_t otg_enable_ic_usb : 1; // 31 IC_USB mode specified for mode of operation +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t op_mode : 3; // 0..2 HNP/SRP Host/Device/OTG mode + uint32_t arch : 2; // 3..4 Slave/External/Internal DMA + uint32_t single_point : 1; // 5 0: support hub and split | 1: no hub, no split + uint32_t hs_phy_type : 2; // 6..7 0: not supported | 1: UTMI+ | 2: ULPI | 3: UTMI+ and ULPI + uint32_t fs_phy_type : 2; // 8..9 0: not supported | 1: dedicated | 2: UTMI+ | 3: ULPI + uint32_t num_dev_ep : 4; // 10..13 Number of device endpoints (excluding EP0) + uint32_t num_host_ch : 4; // 14..17 Number of host channel (excluding control) + uint32_t period_channel_support : 1; // 18 Support Periodic OUT Host Channel + uint32_t enable_dynamic_fifo : 1; // 19 Dynamic FIFO Sizing Enabled + uint32_t mul_proc_intrpt : 1; // 20 Multi-Processor Interrupt enabled (OTG_MULTI_PROC_INTRPT) + uint32_t reserved21 : 1; // 21 reserved + uint32_t nptx_q_depth : 2; // 22..23 Non-periodic request queue depth: 0 = 2. 1 = 4, 2 = 8 + uint32_t ptx_q_depth : 2; // 24..25 Host periodic request queue depth: 0 = 2. 1 = 4, 2 = 8 + uint32_t token_q_depth : 5; // 26..30 Device IN token sequence learning queue depth: 0-30 + uint32_t otg_enable_ic_usb : 1; // 31 IC_USB mode specified for mode of operation + }; } dwc2_ghwcfg2_t; TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg2_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t xfer_size_width : 4; // 0..3 Transfer size counter in bits = 11 + n (max 19 bits) - uint32_t packet_size_width : 3; // 4..6 Packet size counter in bits = 4 + n (max 10 bits) - uint32_t otg_enable : 1; // 7 OTG capable - uint32_t i2c_enable : 1; // 8 I2C interface is available - uint32_t vendor_ctrl_itf : 1; // 9 Vendor control interface is available - uint32_t optional_feature_removed : 1; // 10 remove User ID, GPIO, SOF toggle & counter to save gate count - uint32_t synch_reset : 1; // 11 0: async reset | 1: synch reset - uint32_t otg_adp_support : 1; // 12 ADP logic is present along with HSOTG controller - uint32_t otg_enable_hsic : 1; // 13 1: HSIC-capable with shared UTMI PHY interface | 0: non-HSIC - uint32_t battery_charger_support : 1; // s14 upport battery charger - uint32_t lpm_mode : 1; // 15 LPM mode - uint32_t dfifo_depth : 16; // DFIFO depth - EP_LOC_CNT in terms of 32-bit words -}dwc2_ghwcfg3_t; +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t xfer_size_width : 4; // 0..3 Transfer size counter in bits = 11 + n (max 19 bits) + uint32_t packet_size_width : 3; // 4..6 Packet size counter in bits = 4 + n (max 10 bits) + uint32_t otg_enable : 1; // 7 OTG capable + uint32_t i2c_enable : 1; // 8 I2C interface is available + uint32_t vendor_ctrl_itf : 1; // 9 Vendor control interface is available + uint32_t optional_feature_removed : 1; // 10 remove User ID, GPIO, SOF toggle & counter to save gate count + uint32_t synch_reset : 1; // 11 0: async reset | 1: synch reset + uint32_t otg_adp_support : 1; // 12 ADP logic is present along with HSOTG controller + uint32_t otg_enable_hsic : 1; // 13 1: HSIC-capable with shared UTMI PHY interface | 0: non-HSIC + uint32_t battery_charger_support : 1; // s14 upport battery charger + uint32_t lpm_mode : 1; // 15 LPM mode + uint32_t dfifo_depth : 16; // DFIFO depth - EP_LOC_CNT in terms of 32-bit words + }; +} dwc2_ghwcfg3_t; TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg3_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t num_dev_period_in_ep : 4; // 0..3 Number of Device Periodic IN Endpoints - uint32_t partial_powerdown : 1; // 4 Partial Power Down Enabled - uint32_t ahb_freq_min : 1; // 5 1: minimum of AHB frequency is less than 60 MHz - uint32_t hibernation : 1; // 6 Hibernation feature is enabled - uint32_t extended_hibernation : 1; // 7 Extended Hibernation feature is enabled - uint32_t reserved8 : 1; // 8 Reserved - uint32_t enhanced_lpm_support1 : 1; // 9 Enhanced LPM Support1 - uint32_t service_interval_flow : 1; // 10 Service Interval flow is supported - uint32_t ipg_isoc_support : 1; // 11 Interpacket GAP ISO OUT worst-case is supported - uint32_t acg_support : 1; // 12 Active clock gating is supported - uint32_t enhanced_lpm_support : 1; // 13 Enhanced LPM Support - uint32_t phy_data_width : 2; // 14..15 0: 8 bits | 1: 16 bits | 2: 8/16 software selectable - uint32_t ctrl_ep_num : 4; // 16..19 Number of Device control endpoints in addition to EP0 - uint32_t iddg_filter : 1; // 20 IDDG Filter Enabled - uint32_t vbus_valid_filter : 1; // 21 VBUS Valid Filter Enabled - uint32_t a_valid_filter : 1; // 22 A Valid Filter Enabled - uint32_t b_valid_filter : 1; // 23 B Valid Filter Enabled - uint32_t session_end_filter : 1; // 24 Session End Filter Enabled - uint32_t dedicated_fifos : 1; // 25 Dedicated tx fifo for device IN Endpoint - uint32_t num_dev_in_eps : 4; // 26..29 Number of Device IN Endpoints including EP0 - uint32_t dma_desc_enabled : 1; // scatter/gather DMA configuration enabled - uint32_t dma_desc_dynamic : 1; // Dynamic scatter/gather DMA -}dwc2_ghwcfg4_t; +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t num_dev_period_in_ep : 4; // 0..3 Number of Device Periodic IN Endpoints + uint32_t partial_powerdown : 1; // 4 Partial Power Down Enabled + uint32_t ahb_freq_min : 1; // 5 1: minimum of AHB frequency is less than 60 MHz + uint32_t hibernation : 1; // 6 Hibernation feature is enabled + uint32_t extended_hibernation : 1; // 7 Extended Hibernation feature is enabled + uint32_t reserved8 : 1; // 8 Reserved + uint32_t enhanced_lpm_support1 : 1; // 9 Enhanced LPM Support1 + uint32_t service_interval_flow : 1; // 10 Service Interval flow is supported + uint32_t ipg_isoc_support : 1; // 11 Interpacket GAP ISO OUT worst-case is supported + uint32_t acg_support : 1; // 12 Active clock gating is supported + uint32_t enhanced_lpm_support : 1; // 13 Enhanced LPM Support + uint32_t phy_data_width : 2; // 14..15 0: 8 bits | 1: 16 bits | 2: 8/16 software selectable + uint32_t ctrl_ep_num : 4; // 16..19 Number of Device control endpoints in addition to EP0 + uint32_t iddg_filter : 1; // 20 IDDG Filter Enabled + uint32_t vbus_valid_filter : 1; // 21 VBUS Valid Filter Enabled + uint32_t a_valid_filter : 1; // 22 A Valid Filter Enabled + uint32_t b_valid_filter : 1; // 23 B Valid Filter Enabled + uint32_t session_end_filter : 1; // 24 Session End Filter Enabled + uint32_t dedicated_fifos : 1; // 25 Dedicated tx fifo for device IN Endpoint + uint32_t num_dev_in_eps : 4; // 26..29 Number of Device IN Endpoints including EP0 + uint32_t dma_desc_enabled : 1; // scatter/gather DMA configuration enabled + uint32_t dma_desc_dynamic : 1; // Dynamic scatter/gather DMA + }; +} dwc2_ghwcfg4_t; TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg4_t) == 4, "incorrect size"); -//-------------------------------------------------------------------- -// Host Register Bitfield -//-------------------------------------------------------------------- - -typedef struct TU_ATTR_PACKED { - uint32_t fifo_available : 16; // 0..15 Number of words available in the Tx FIFO - uint32_t req_queue_available : 8; // 16..23 Number of spaces available in the NPT transmit request queue for both IN and OU - // 24..31 is top entry in the request queue that is currently being processed by the MAC - uint32_t qtop_terminate : 1; // 24 Last entry for selected channel - uint32_t qtop_type : 2; // 25..26 Token (0) In/Out (1) ZLP, (2) Ping/cspit, (3) Channel halt command - uint32_t qtop_ch_num : 4; // 27..30 Channel number +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t fifo_available : 16; // 0..15 Number of words available in the Tx FIFO + uint32_t req_queue_available : 8; // 16..23 Number of spaces available in the NPT transmit request queue for both IN and OU + // 24..31 is top entry in the request queue that is currently being processed by the MAC + uint32_t qtop_terminate : 1; // 24 Last entry for selected channel + uint32_t qtop_type : 2; // 25..26 Token (0) In/Out (1) ZLP, (2) Ping/cspit, (3) Channel halt command + uint32_t qtop_ch_num : 4; // 27..30 Channel number + }; } dwc2_hnptxsts_t; TU_VERIFY_STATIC(sizeof(dwc2_hnptxsts_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t fifo_available : 16; // 0..15 Number of words available in the Tx FIFO - uint32_t req_queue_available : 7; // 16..22 Number of spaces available in the PTX transmit request queue - uint32_t qtop_terminate : 1; // 23 Last entry for selected channel - uint32_t qtop_last_period : 1; // 24 Last entry for selected channel is a periodic entry - uint32_t qtop_type : 2; // 25..26 Token (0) In/Out (1) ZLP, (2) Ping/cspit, (3) Channel halt command - uint32_t qtop_ch_num : 4; // 27..30 Channel number - uint32_t qtop_odd_frame : 1; // 31 Send in odd frame +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t fifo_available : 16; // 0..15 Number of words available in the Tx FIFO + uint32_t req_queue_available : 7; // 16..22 Number of spaces available in the PTX transmit request queue + uint32_t qtop_terminate : 1; // 23 Last entry for selected channel + uint32_t qtop_last_period : 1; // 24 Last entry for selected channel is a periodic entry + uint32_t qtop_type : 2; // 25..26 Token (0) In/Out (1) ZLP, (2) Ping/cspit, (3) Channel halt command + uint32_t qtop_ch_num : 4; // 27..30 Channel number + uint32_t qtop_odd_frame : 1; // 31 Send in odd frame + }; } dwc2_hptxsts_t; TU_VERIFY_STATIC(sizeof(dwc2_hptxsts_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t conn_status : 1; // 0 Port connect status - uint32_t conn_detected : 1; // 1 Port connect detected - uint32_t enable : 1; // 2 Port enable status - uint32_t enable_change : 1; // 3 Port enable change - uint32_t over_current_active : 1; // 4 Port Over-current active - uint32_t over_current_change : 1; // 5 Port Over-current change - uint32_t resume : 1; // 6 Port resume - uint32_t suspend : 1; // 7 Port suspend - uint32_t reset : 1; // 8 Port reset - uint32_t rsv9 : 1; // 9 Reserved - uint32_t line_status : 2; // 10..11 Line status - uint32_t power : 1; // 12 Port power - uint32_t test_control : 4; // 13..16 Port Test control - uint32_t speed : 2; // 17..18 Port speed - uint32_t rsv19_31 :13; // 19..31 Reserved -}dwc2_hprt_t; +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t conn_status : 1; // 0 Port connect status + uint32_t conn_detected : 1; // 1 Port connect detected + uint32_t enable : 1; // 2 Port enable status + uint32_t enable_change : 1; // 3 Port enable change + uint32_t over_current_active : 1; // 4 Port Over-current active + uint32_t over_current_change : 1; // 5 Port Over-current change + uint32_t resume : 1; // 6 Port resume + uint32_t suspend : 1; // 7 Port suspend + uint32_t reset : 1; // 8 Port reset + uint32_t rsv9 : 1; // 9 Reserved + uint32_t line_status : 2; // 10..11 Line status + uint32_t power : 1; // 12 Port power + uint32_t test_control : 4; // 13..16 Port Test control + uint32_t speed : 2; // 17..18 Port speed + uint32_t rsv19_31 :13; // 19..31 Reserved + }; +} dwc2_hprt_t; TU_VERIFY_STATIC(sizeof(dwc2_hprt_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t ep_size : 11; // 0..10 Maximum packet size - uint32_t ep_num : 4; // 11..14 Endpoint number - uint32_t ep_dir : 1; // 15 Endpoint direction - uint32_t rsv16 : 1; // 16 Reserved - uint32_t low_speed_dev : 1; // 17 Low-speed device - uint32_t ep_type : 2; // 18..19 Endpoint type - uint32_t err_multi_count : 2; // 20..21 Error (splitEn = 1) / Multi (SplitEn = 0) count - uint32_t dev_addr : 7; // 22..28 Device address - uint32_t odd_frame : 1; // 29 Odd frame - uint32_t disable : 1; // 30 Channel disable - uint32_t enable : 1; // 31 Channel enable +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t ep_size : 11; // 0..10 Maximum packet size + uint32_t ep_num : 4; // 11..14 Endpoint number + uint32_t ep_dir : 1; // 15 Endpoint direction + uint32_t rsv16 : 1; // 16 Reserved + uint32_t low_speed_dev : 1; // 17 Low-speed device + uint32_t ep_type : 2; // 18..19 Endpoint type + uint32_t err_multi_count : 2; // 20..21 Error (splitEn = 1) / Multi (SplitEn = 0) count + uint32_t dev_addr : 7; // 22..28 Device address + uint32_t odd_frame : 1; // 29 Odd frame + uint32_t disable : 1; // 30 Channel disable + uint32_t enable : 1; // 31 Channel enable + }; } dwc2_channel_char_t; TU_VERIFY_STATIC(sizeof(dwc2_channel_char_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t hub_port : 7; // 0..6 Hub port number - uint32_t hub_addr : 7; // 7..13 Hub address - uint32_t xact_pos : 2; // 14..15 Transaction position - uint32_t split_compl : 1; // 16 Split completion - uint32_t rsv17_30 : 14; // 17..30 Reserved - uint32_t split_en : 1; // 31 Split enable +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t hub_port : 7; // 0..6 Hub port number + uint32_t hub_addr : 7; // 7..13 Hub address + uint32_t xact_pos : 2; // 14..15 Transaction position + uint32_t split_compl : 1; // 16 Split completion + uint32_t rsv17_30 : 14; // 17..30 Reserved + uint32_t split_en : 1; // 31 Split enable + }; } dwc2_channel_split_t; TU_VERIFY_STATIC(sizeof(dwc2_channel_split_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t xfer_size : 19; // 0..18 Transfer size in bytes - uint32_t packet_count : 10; // 19..28 Number of packets - uint32_t pid : 2; // 29..30 Packet ID - uint32_t do_ping : 1; // 31 Do PING +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t xfer_size : 19; // 0..18 Transfer size in bytes + uint32_t packet_count : 10; // 19..28 Number of packets + uint32_t pid : 2; // 29..30 Packet ID + uint32_t do_ping : 1; // 31 Do PING + }; } dwc2_channel_tsize_t; TU_VERIFY_STATIC(sizeof(dwc2_channel_tsize_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t num : 16; // 0..15 Frame number - uint32_t remainning : 16; // 16..31 Frame remaining +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t num : 16; // 0..15 Frame number + uint32_t remainning : 16; // 16..31 Frame remaining + }; } dwc2_hfnum_t; TU_VERIFY_STATIC(sizeof(dwc2_hfnum_t) == 4, "incorrect size"); // Host Channel typedef struct { - union { - volatile uint32_t hcchar; // 500 + 20*ch Host Channel Characteristics - volatile dwc2_channel_char_t hcchar_bm; - }; - union { - volatile uint32_t hcsplt; // 504 + 20*ch Host Channel Split Control - volatile dwc2_channel_split_t hcsplt_bm; - }; - volatile uint32_t hcint; // 508 + 20*ch Host Channel Interrupt - volatile uint32_t hcintmsk; // 50C + 20*ch Host Channel Interrupt Mask - union { - volatile uint32_t hctsiz; // 510 + 20*ch Host Channel Transfer Size - volatile dwc2_channel_tsize_t hctsiz_bm; - }; - volatile uint32_t hcdma; // 514 + 20*ch Host Channel DMA Address - uint32_t reserved518; // 518 + 20*ch - volatile uint32_t hcdmab; // 51C + 20*ch Host Channel DMA Address + volatile uint32_t hcchar; // 500 + 20*ch Host Channel Characteristics + volatile uint32_t hcsplt; // 504 + 20*ch Host Channel Split Control + volatile uint32_t hcint; // 508 + 20*ch Host Channel Interrupt + volatile uint32_t hcintmsk; // 50C + 20*ch Host Channel Interrupt Mask + volatile uint32_t hctsiz; // 510 + 20*ch Host Channel Transfer Size + volatile uint32_t hcdma; // 514 + 20*ch Host Channel DMA Address + uint32_t reserved518; // 518 + 20*ch + volatile uint32_t hcdmab; // 51C + 20*ch Host Channel DMA Address } dwc2_channel_t; //-------------------------------------------------------------------- // Device Register Bitfield //-------------------------------------------------------------------- -typedef struct TU_ATTR_PACKED { - uint32_t speed : 2; // 0..1 Speed - uint32_t nzsts_out_handshake : 1; // 2 Non-zero-length status OUT handshake - uint32_t en_32khz_suspsend : 1; // 3 Enable 32-kHz SUSPEND mode - uint32_t address : 7; // 4..10 Device address - uint32_t period_frame_interval : 2; // 11..12 Periodic frame interval - uint32_t en_out_nak : 1; // 13 Enable Device OUT NAK - uint32_t xcvr_delay : 1; // 14 Transceiver delay - uint32_t erratic_int_mask : 1; // 15 Erratic interrupt mask - uint32_t rsv16 : 1; // 16 Reserved - uint32_t ipg_iso_support : 1; // 17 Interpacket gap ISO support - uint32_t epin_mismatch_count : 5; // 18..22 EP IN mismatch count - uint32_t dma_desc : 1; // 23 Enable scatter/gatter DMA descriptor - uint32_t period_schedule_interval : 2; // 24..25 Periodic schedule interval for scatter/gatter DMA - uint32_t resume_valid : 6; // 26..31 Resume valid period +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t speed : 2; // 0..1 Speed + uint32_t nzsts_out_handshake : 1; // 2 Non-zero-length status OUT handshake + uint32_t en_32khz_suspsend : 1; // 3 Enable 32-kHz SUSPEND mode + uint32_t address : 7; // 4..10 Device address + uint32_t period_frame_interval : 2; // 11..12 Periodic frame interval + uint32_t en_out_nak : 1; // 13 Enable Device OUT NAK + uint32_t xcvr_delay : 1; // 14 Transceiver delay + uint32_t erratic_int_mask : 1; // 15 Erratic interrupt mask + uint32_t rsv16 : 1; // 16 Reserved + uint32_t ipg_iso_support : 1; // 17 Interpacket gap ISO support + uint32_t epin_mismatch_count : 5; // 18..22 EP IN mismatch count + uint32_t dma_desc : 1; // 23 Enable scatter/gather DMA descriptor + uint32_t period_schedule_interval : 2; // 24..25 Periodic schedule interval for scatter/gather DMA + uint32_t resume_valid : 6; // 26..31 Resume valid period + }; } dwc2_dcfg_t; TU_VERIFY_STATIC(sizeof(dwc2_dcfg_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t remote_wakeup_signal : 1; // 0 Remote wakeup signal - uint32_t soft_disconnet : 1; // 1 Soft disconnect - uint32_t gnp_in_nak_status : 1; // 2 Global non-periodic NAK IN status - uint32_t gout_nak_status : 1; // 3 Global OUT NAK status - uint32_t test_control : 3; // 4..6 Test control - uint32_t set_gnp_in_nak : 1; // 7 Set global non-periodic IN NAK - uint32_t clear_gnp_in_nak : 1; // 8 Clear global non-periodic IN NAK - uint32_t set_gout_nak : 1; // 9 Set global OUT NAK - uint32_t clear_gout_nak : 1; // 10 Clear global OUT NAK - uint32_t poweron_prog_done : 1; // 11 Power-on programming done - uint32_t rsv12 : 1; // 12 Reserved - uint32_t global_multi_count : 2; // 13..14 Global multi-count - uint32_t ignore_frame_number : 1; // 15 Ignore frame number - uint32_t nak_on_babble : 1; // 16 NAK on babble - uint32_t en_cont_on_bna : 1; // 17 Enable continue on BNA - uint32_t deep_sleep_besl_reject : 1; // 18 Deep sleep BESL reject - uint32_t service_interval : 1; // 19 Service interval for ISO IN endpoint - uint32_t rsv20_31 :12; // 20..31 Reserved +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t remote_wakeup_signal : 1; // 0 Remote wakeup signal + uint32_t soft_disconnet : 1; // 1 Soft disconnect + uint32_t gnp_in_nak_status : 1; // 2 Global non-periodic NAK IN status + uint32_t gout_nak_status : 1; // 3 Global OUT NAK status + uint32_t test_control : 3; // 4..6 Test control + uint32_t set_gnp_in_nak : 1; // 7 Set global non-periodic IN NAK + uint32_t clear_gnp_in_nak : 1; // 8 Clear global non-periodic IN NAK + uint32_t set_gout_nak : 1; // 9 Set global OUT NAK + uint32_t clear_gout_nak : 1; // 10 Clear global OUT NAK + uint32_t poweron_prog_done : 1; // 11 Power-on programming done + uint32_t rsv12 : 1; // 12 Reserved + uint32_t global_multi_count : 2; // 13..14 Global multi-count + uint32_t ignore_frame_number : 1; // 15 Ignore frame number + uint32_t nak_on_babble : 1; // 16 NAK on babble + uint32_t en_cont_on_bna : 1; // 17 Enable continue on BNA + uint32_t deep_sleep_besl_reject : 1; // 18 Deep sleep BESL reject + uint32_t service_interval : 1; // 19 Service interval for ISO IN endpoint + uint32_t rsv20_31 :12; // 20..31 Reserved + }; } dwc2_dctl_t; TU_VERIFY_STATIC(sizeof(dwc2_dctl_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t suspend_status : 1; // 0 Suspend status - uint32_t enum_speed : 2; // 1..2 Enumerated speed - uint32_t erratic_err : 1; // 3 Erratic error - uint32_t rsv4_7 : 4; // 4..7 Reserved - uint32_t frame_number : 14; // 8..21 Frame/MicroFrame number - uint32_t line_status : 2; // 22..23 Line status - uint32_t rsv24_31 : 8; // 24..31 Reserved +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t suspend_status : 1; // 0 Suspend status + uint32_t enum_speed : 2; // 1..2 Enumerated speed + uint32_t erratic_err : 1; // 3 Erratic error + uint32_t rsv4_7 : 4; // 4..7 Reserved + uint32_t frame_number : 14; // 8..21 Frame/MicroFrame number + uint32_t line_status : 2; // 22..23 Line status + uint32_t rsv24_31 : 8; // 24..31 Reserved + }; } dwc2_dsts_t; TU_VERIFY_STATIC(sizeof(dwc2_dsts_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t xfer_complete : 1; // 0 Transfer complete - uint32_t disabled : 1; // 1 Endpoint disabled - uint32_t ahb_err : 1; // 2 AHB error - uint32_t timeout : 1; // 3 Timeout - uint32_t in_rx_txfe : 1; // 4 IN token received when TxFIFO is empty - uint32_t in_rx_ep_mismatch : 1; // 5 IN token received with EP mismatch - uint32_t in_ep_nak_effective : 1; // 6 IN endpoint NAK effective - uint32_t txfifo_empty : 1; // 7 TX FIFO empty - uint32_t txfifo_underrun : 1; // 8 Tx FIFO under run - uint32_t bna : 1; // 9 Buffer not available - uint32_t rsv10 : 1; // 10 Reserved - uint32_t iso_packet_drop : 1; // 11 Isochronous OUT packet drop status - uint32_t babble_err : 1; // 12 Babble error - uint32_t nak : 1; // 13 NAK - uint32_t nyet : 1; // 14 NYET - uint32_t rsv14_31 :17; // 15..31 Reserved +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t xfer_complete : 1; // 0 Transfer complete + uint32_t disabled : 1; // 1 Endpoint disabled + uint32_t ahb_err : 1; // 2 AHB error + uint32_t timeout : 1; // 3 Timeout + uint32_t in_rx_txfe : 1; // 4 IN token received when TxFIFO is empty + uint32_t in_rx_ep_mismatch : 1; // 5 IN token received with EP mismatch + uint32_t in_ep_nak_effective : 1; // 6 IN endpoint NAK effective + uint32_t txfifo_empty : 1; // 7 TX FIFO empty + uint32_t txfifo_underrun : 1; // 8 Tx FIFO under run + uint32_t bna : 1; // 9 Buffer not available + uint32_t rsv10 : 1; // 10 Reserved + uint32_t iso_packet_drop : 1; // 11 Isochronous OUT packet drop status + uint32_t babble_err : 1; // 12 Babble error + uint32_t nak : 1; // 13 NAK + uint32_t nyet : 1; // 14 NYET + uint32_t rsv14_31 :17; // 15..31 Reserved + }; } dwc2_diepint_t; TU_VERIFY_STATIC(sizeof(dwc2_diepint_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t mps : 11; // 0..10 Maximum packet size, EP0 only use 2 bit - uint32_t next_ep : 4; // 11..14 Next endpoint number - uint32_t active : 1; // 15 Active - const uint32_t dpid_iso_odd : 1; // 16 DATA0/DATA1 for bulk/interrupt, odd frame for isochronous - const uint32_t nak_status : 1; // 17 NAK status - uint32_t type : 2; // 18..19 Endpoint type - uint32_t rsv20 : 1; // 20 Reserved - uint32_t stall : 1; // 21 Stall - uint32_t tx_fifo_num : 4; // 22..25 Tx FIFO number (IN) - uint32_t clear_nak : 1; // 26 Clear NAK - uint32_t set_nak : 1; // 27 Set NAK - uint32_t set_data0_iso_even : 1; // 28 Set DATA0 if bulk/interrupt, even frame for isochronous - uint32_t set_data1_iso_odd : 1; // 29 Set DATA1 if bulk/interrupt, odd frame for isochronous - uint32_t disable : 1; // 30 Disable - uint32_t enable : 1; // 31 Enable +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t mps : 11; // 0..10 Maximum packet size, EP0 only use 2 bits + uint32_t next_ep : 4; // 11..14 Next endpoint number + uint32_t active : 1; // 15 Active + uint32_t dpid_iso_odd : 1; // 16 DATA0/DATA1 for bulk/interrupt, odd frame for isochronous + uint32_t nak_status : 1; // 17 NAK status + uint32_t type : 2; // 18..19 Endpoint type + uint32_t rsv20 : 1; // 20 Reserved + uint32_t stall : 1; // 21 Stall + uint32_t tx_fifo_num : 4; // 22..25 Tx FIFO number (IN) + uint32_t clear_nak : 1; // 26 Clear NAK + uint32_t set_nak : 1; // 27 Set NAK + uint32_t set_data0_iso_even : 1; // 28 Set DATA0 if bulk/interrupt, even frame for isochronous + uint32_t set_data1_iso_odd : 1; // 29 Set DATA1 if bulk/interrupt, odd frame for isochronous + uint32_t disable : 1; // 30 Disable + uint32_t enable : 1; // 31 Enable + }; } dwc2_depctl_t; TU_VERIFY_STATIC(sizeof(dwc2_depctl_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t xfer_complete : 1; // 0 Transfer complete - uint32_t disabled : 1; // 1 Endpoint disabled - uint32_t ahb_err : 1; // 2 AHB error - uint32_t setup_phase_done : 1; // 3 Setup phase done - uint32_t out_rx_ep_disabled : 1; // 4 OUT token received when endpoint disabled - uint32_t status_phase_rx : 1; // 5 Status phase received - uint32_t setup_b2b : 1; // 6 Setup packet back-to-back - uint32_t rsv7 : 1; // 7 Reserved - uint32_t out_packet_err : 1; // 8 OUT packet error - uint32_t bna : 1; // 9 Buffer not available - uint32_t rsv10 : 1; // 10 Reserved - uint32_t iso_packet_drop : 1; // 11 Isochronous OUT packet drop status - uint32_t babble_err : 1; // 12 Babble error - uint32_t nak : 1; // 13 NAK - uint32_t nyet : 1; // 14 NYET - uint32_t setup_packet_rx : 1; // 15 Setup packet received (Buffer DMA Mode only) - uint32_t rsv16_31 :16; // 16..31 Reserved +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t xfer_complete : 1; // 0 Transfer complete + uint32_t disabled : 1; // 1 Endpoint disabled + uint32_t ahb_err : 1; // 2 AHB error + uint32_t setup_phase_done : 1; // 3 Setup phase done + uint32_t out_rx_ep_disabled : 1; // 4 OUT token received when endpoint disabled + uint32_t status_phase_rx : 1; // 5 Status phase received + uint32_t setup_b2b : 1; // 6 Setup packet back-to-back + uint32_t rsv7 : 1; // 7 Reserved + uint32_t out_packet_err : 1; // 8 OUT packet error + uint32_t bna : 1; // 9 Buffer not available + uint32_t rsv10 : 1; // 10 Reserved + uint32_t iso_packet_drop : 1; // 11 Isochronous OUT packet drop status + uint32_t babble_err : 1; // 12 Babble error + uint32_t nak : 1; // 13 NAK + uint32_t nyet : 1; // 14 NYET + uint32_t setup_packet_rx : 1; // 15 Setup packet received (Buffer DMA Mode only) + uint32_t rsv16_31 :16; // 16..31 Reserved + }; } dwc2_doepint_t; TU_VERIFY_STATIC(sizeof(dwc2_doepint_t) == 4, "incorrect size"); -typedef struct TU_ATTR_PACKED { - uint32_t xfer_size : 19; // 0..18 Transfer size in bytes - uint32_t packet_count : 10; // 19..28 Number of packets - uint32_t mc_pid : 2; // 29..30 IN: Multi Count, OUT: PID +typedef union { + uint32_t value; + struct TU_ATTR_PACKED { + uint32_t xfer_size : 19; // 0..18 Transfer size in bytes + uint32_t packet_count : 10; // 19..28 Number of packets + uint32_t mc_pid : 2; // 29..30 IN: Multi Count, OUT: PID + }; } dwc2_ep_tsize_t; TU_VERIFY_STATIC(sizeof(dwc2_ep_tsize_t) == 4, "incorrect size"); @@ -601,26 +656,19 @@ typedef struct { union { volatile uint32_t diepctl; volatile uint32_t doepctl; - volatile uint32_t ctl; - volatile dwc2_depctl_t ctl_bm; }; uint32_t rsv04; union { volatile uint32_t intr; - volatile uint32_t diepint; - volatile dwc2_diepint_t diepint_bm; - volatile uint32_t doepint; - volatile dwc2_doepint_t doepint_bm; }; uint32_t rsv0c; union { volatile uint32_t dieptsiz; volatile uint32_t doeptsiz; volatile uint32_t tsiz; - volatile dwc2_ep_tsize_t tsiz_bm; }; union { volatile uint32_t diepdma; @@ -628,7 +676,7 @@ typedef struct { }; volatile uint32_t dtxfsts; uint32_t rsv1c; -}dwc2_dep_t; +} dwc2_dep_t; TU_VERIFY_STATIC(sizeof(dwc2_dep_t) == 0x20, "incorrect size"); @@ -637,156 +685,107 @@ TU_VERIFY_STATIC(sizeof(dwc2_dep_t) == 0x20, "incorrect size"); //-------------------------------------------------------------------- typedef struct { //------------- Core Global -------------// - union { - volatile uint32_t gotgctl; // 000 OTG Control and Status - volatile dwc2_gotgctl_t gotgctl_bm; - }; - union { - volatile uint32_t gotgint; // 004 OTG Interrupt - volatile dwc2_gotgint_t gotgint_bm; - }; - union { - volatile uint32_t gahbcfg; // 008 AHB Configuration - volatile dwc2_gahbcfg_t gahbcfg_bm; - }; - union { - volatile uint32_t gusbcfg; // 00c USB Configuration - volatile dwc2_gusbcfg_t gusbcfg_bm; - }; - union { - volatile uint32_t grstctl; // 010 Reset - volatile dwc2_grstctl_t grstctl_bm; - }; - volatile uint32_t gintsts; // 014 Interrupt - volatile uint32_t gintmsk; // 018 Interrupt Mask - volatile uint32_t grxstsr; // 01c Receive Status Debug Read - union { - volatile uint32_t grxstsp; // 020 Receive Status Read/Pop - volatile dwc2_grxstsp_t grxstsp_bm; - }; - volatile uint32_t grxfsiz; // 024 Receive FIFO Size + volatile uint32_t gotgctl; // 000 OTG Control and Status + volatile uint32_t gotgint; // 004 OTG Interrupt + volatile uint32_t gahbcfg; // 008 AHB Configuration + volatile uint32_t gusbcfg; // 00c USB Configuration + volatile uint32_t grstctl; // 010 Reset + volatile uint32_t gintsts; // 014 Interrupt + volatile uint32_t gintmsk; // 018 Interrupt Mask + volatile uint32_t grxstsr; // 01c Receive Status Debug Read + volatile uint32_t grxstsp; // 020 Receive Status Read/Pop + volatile uint32_t grxfsiz; // 024 Receive FIFO Size union { volatile uint32_t dieptxf0; // 028 EP0 Tx FIFO Size volatile uint32_t gnptxfsiz; // 028 Non-periodic Transmit FIFO Size }; union { volatile uint32_t hnptxsts; // 02c Non-periodic Transmit FIFO/Queue Status - volatile dwc2_hnptxsts_t hnptxsts_bm; volatile uint32_t gnptxsts; }; - volatile uint32_t gi2cctl; // 030 I2C Address - volatile uint32_t gpvndctl; // 034 PHY Vendor Control + volatile uint32_t gi2cctl; // 030 I2C Address + volatile uint32_t gpvndctl; // 034 PHY Vendor Control union { volatile uint32_t ggpio; // 038 General Purpose IO volatile uint32_t stm32_gccfg; // 038 STM32 General Core Configuration }; - volatile uint32_t guid; // 03C User (Application programmable) ID - volatile uint32_t gsnpsid; // 040 Synopsys ID + Release version - volatile uint32_t ghwcfg1; // 044 User Hardware Configuration1: endpoint dir (2 bit per ep) - union { - volatile uint32_t ghwcfg2; // 048 User Hardware Configuration2 - volatile dwc2_ghwcfg2_t ghwcfg2_bm; - }; - union { - volatile uint32_t ghwcfg3; // 04C User Hardware Configuration3 - volatile dwc2_ghwcfg3_t ghwcfg3_bm; - }; + volatile uint32_t guid; // 03C User (Application programmable) ID + volatile uint32_t gsnpsid; // 040 Synopsys ID + Release version + volatile uint32_t ghwcfg1; // 044 User Hardware Configuration1: endpoint dir (2 bit per ep) + volatile uint32_t ghwcfg2; // 048 User Hardware Configuration2 + volatile uint32_t ghwcfg3; // 04C User Hardware Configuration3 union { volatile uint32_t ghwcfg4; // 050 User Hardware Configuration4 volatile dwc2_ghwcfg4_t ghwcfg4_bm; }; - volatile uint32_t glpmcfg; // 054 Core LPM Configuration - volatile uint32_t gpwrdn; // 058 Power Down - volatile uint32_t gdfifocfg; // 05C DFIFO Software Configuration - volatile uint32_t gadpctl; // 060 ADP Timer, Control and Status - uint32_t reserved64[39]; // 064..0FF - volatile uint32_t hptxfsiz; // 100 Host Periodic Tx FIFO Size - volatile uint32_t dieptxf[15]; // 104..13C Device Periodic Transmit FIFO Size - uint32_t reserved140[176]; // 140..3FF + volatile uint32_t glpmcfg; // 054 Core LPM Configuration + volatile uint32_t gpwrdn; // 058 Power Down + volatile uint32_t gdfifocfg; // 05C DFIFO Software Configuration + volatile uint32_t gadpctl; // 060 ADP Timer, Control and Status + uint32_t reserved64[39]; // 064..0FF + volatile uint32_t hptxfsiz; // 100 Host Periodic Tx FIFO Size + volatile uint32_t dieptxf[15]; // 104..13C Device Periodic Transmit FIFO Size + uint32_t reserved140[176]; // 140..3FF - //------------ Host -------------// - volatile uint32_t hcfg; // 400 Host Configuration - volatile uint32_t hfir; // 404 Host Frame Interval - union { - volatile uint32_t hfnum; // 408 Host Frame Number / Frame Remaining - volatile dwc2_hfnum_t hfnum_bm; - }; - uint32_t reserved40c; // 40C - union { - volatile uint32_t hptxsts; // 410 Host Periodic TX FIFO / Queue Status - volatile dwc2_hptxsts_t hptxsts_bm; - }; - volatile uint32_t haint; // 414 Host All Channels Interrupt - volatile uint32_t haintmsk; // 418 Host All Channels Interrupt Mask - volatile uint32_t hflbaddr; // 41C Host Frame List Base Address - uint32_t reserved420[8]; // 420..43F - union { - volatile uint32_t hprt; // 440 Host Port Control and Status - volatile dwc2_hprt_t hprt_bm; - }; - uint32_t reserved444[47]; // 444..4FF + //------------ Host -------------// + volatile uint32_t hcfg; // 400 Host Configuration + volatile uint32_t hfir; // 404 Host Frame Interval + volatile uint32_t hfnum; // 408 Host Frame Number / Frame Remaining + uint32_t reserved40c; // 40C + volatile uint32_t hptxsts; // 410 Host Periodic TX FIFO / Queue Status + volatile uint32_t haint; // 414 Host All Channels Interrupt + volatile uint32_t haintmsk; // 418 Host All Channels Interrupt Mask + volatile uint32_t hflbaddr; // 41C Host Frame List Base Address + uint32_t reserved420[8]; // 420..43F + volatile uint32_t hprt; // 440 Host Port Control and Status + uint32_t reserved444[47]; // 444..4FF - //------------- Host Channel -------------// - dwc2_channel_t channel[16]; // 500..6FF Host Channels 0-15 - uint32_t reserved700[64]; // 700..7FF + //------------- Host Channel -------------// + dwc2_channel_t channel[16]; // 500..6FF Host Channels 0-15 + uint32_t reserved700[64]; // 700..7FF - //------------- Device -----------// - union { - volatile uint32_t dcfg; // 800 Device Configuration - volatile dwc2_dcfg_t dcfg_bm; - }; - union { - volatile uint32_t dctl; // 804 Device Control - volatile dwc2_dctl_t dctl_bm; - }; - union { - volatile uint32_t dsts; // 808 Device Status (RO) - volatile dwc2_dsts_t dsts_bm; - }; - uint32_t reserved80c; // 80C - union { - volatile uint32_t diepmsk; // 810 Device IN Endpoint Interrupt Mask - volatile dwc2_diepint_t diepmsk_bm; - }; - union { - volatile uint32_t doepmsk; // 814 Device OUT Endpoint Interrupt Mask - volatile dwc2_doepint_t doepmsk_bm; - }; - volatile uint32_t daint; // 818 Device All Endpoints Interrupt - volatile uint32_t daintmsk; // 81C Device All Endpoints Interrupt Mask - volatile uint32_t dtknqr1; // 820 Device IN token sequence learning queue read1 - volatile uint32_t dtknqr2; // 824 Device IN token sequence learning queue read2 - volatile uint32_t dvbusdis; // 828 Device VBUS Discharge Time - volatile uint32_t dvbuspulse; // 82C Device VBUS Pulsing Time - volatile uint32_t dthrctl; // 830 Device threshold Control - volatile uint32_t diepempmsk; // 834 Device IN Endpoint FIFO Empty Interrupt Mask + //------------- Device -----------// + volatile uint32_t dcfg; // 800 Device Configuration + volatile uint32_t dctl; // 804 Device Control + volatile uint32_t dsts; // 808 Device Status (RO) + uint32_t reserved80c; // 80C + volatile uint32_t diepmsk; // 810 Device IN Endpoint Interrupt Mask + volatile uint32_t doepmsk; // 814 Device OUT Endpoint Interrupt Mask + volatile uint32_t daint; // 818 Device All Endpoints Interrupt + volatile uint32_t daintmsk; // 81C Device All Endpoints Interrupt Mask + volatile uint32_t dtknqr1; // 820 Device IN token sequence learning queue read1 + volatile uint32_t dtknqr2; // 824 Device IN token sequence learning queue read2 + volatile uint32_t dvbusdis; // 828 Device VBUS Discharge Time + volatile uint32_t dvbuspulse; // 82C Device VBUS Pulsing Time + volatile uint32_t dthrctl; // 830 Device threshold Control + volatile uint32_t diepempmsk; // 834 Device IN Endpoint FIFO Empty Interrupt Mask - // Device Each Endpoint (IN/OUT) Interrupt/Mask for generating dedicated EP interrupt line - // require OTG_MULTI_PROC_INTRPT=1 - volatile uint32_t deachint; // 838 Device Each Endpoint Interrupt - volatile uint32_t deachmsk; // 83C Device Each Endpoint Interrupt mask - volatile uint32_t diepeachmsk[16]; // 840..87C Device Each IN Endpoint mask - volatile uint32_t doepeachmsk[16]; // 880..8BF Device Each OUT Endpoint mask - uint32_t reserved8c0[16]; // 8C0..8FF + // Device Each Endpoint (IN/OUT) Interrupt/Mask for generating dedicated EP interrupt line + // require OTG_MULTI_PROC_INTRPT=1 + volatile uint32_t deachint; // 838 Device Each Endpoint Interrupt + volatile uint32_t deachmsk; // 83C Device Each Endpoint Interrupt mask + volatile uint32_t diepeachmsk[16]; // 840..87C Device Each IN Endpoint mask + volatile uint32_t doepeachmsk[16]; // 880..8BF Device Each OUT Endpoint mask + uint32_t reserved8c0[16]; // 8C0..8FF - //------------- Device Endpoint -------------// - union { - dwc2_dep_t ep[2][16]; // 0: IN, 1 OUT - struct { - dwc2_dep_t epin[16]; // 900..AFF IN Endpoints - dwc2_dep_t epout[16]; // B00..CFF OUT Endpoints - }; + //------------- Device Endpoint -------------// + union { + dwc2_dep_t ep[2][16]; // 0: IN, 1 OUT + struct { + dwc2_dep_t epin[16]; // 900..AFF IN Endpoints + dwc2_dep_t epout[16]; // B00..CFF OUT Endpoints }; - uint32_t reservedd00[64]; // D00..DFF + }; + uint32_t reservedd00[64]; // D00..DFF - //------------- Power Clock -------------// - volatile uint32_t pcgcctl; // E00 Power and Clock Gating Characteristic Control - volatile uint32_t pcgcctl1; // E04 Power and Clock Gating Characteristic Control 1 - uint32_t reservede08[126]; // E08..FFF + //------------- Power Clock -------------// + volatile uint32_t pcgcctl; // E00 Power and Clock Gating Characteristic Control + volatile uint32_t pcgcctl1; // E04 Power and Clock Gating Characteristic Control 1 + uint32_t reservede08[126]; // E08..FFF - //------------- FIFOs -------------// - // Word-accessed only using first pointer since it auto shift - volatile uint32_t fifo[16][0x400]; // 1000..FFFF Endpoint FIFO + //------------- FIFOs -------------// + // Word-accessed only using first pointer since it auto shift + volatile uint32_t fifo[16][0x400]; // 1000..FFFF Endpoint FIFO } dwc2_regs_t; TU_VERIFY_STATIC(offsetof(dwc2_regs_t, hcfg ) == 0x0400, "incorrect size"); diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index b13479b02..af17bb59a 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -44,7 +44,7 @@ #endif #define DWC2_CHANNEL_COUNT_MAX 16 // absolute max channel count -#define DWC2_CHANNEL_COUNT(_dwc2) tu_min8((_dwc2)->ghwcfg2_bm.num_host_ch + 1, DWC2_CHANNEL_COUNT_MAX) +#define DWC2_CHANNEL_COUNT(_dwc2) ({const dwc2_ghwcfg2_t ghwcfg2 = {.value = (_dwc2)->ghwcfg2}; tu_min8(ghwcfg2.num_host_ch + 1, DWC2_CHANNEL_COUNT_MAX);}) TU_VERIFY_STATIC(CFG_TUH_DWC2_ENDPOINT_MAX <= 255, "currently only use 8-bit for index"); @@ -118,7 +118,8 @@ hcd_data_t _hcd_data; //-------------------------------------------------------------------- TU_ATTR_ALWAYS_INLINE static inline tusb_speed_t hprt_speed_get(dwc2_regs_t* dwc2) { tusb_speed_t speed; - switch(dwc2->hprt_bm.speed) { + const dwc2_hprt_t hprt = {.value = dwc2->hprt}; + switch(hprt.speed) { case HPRT_SPEED_HIGH: speed = TUSB_SPEED_HIGH; break; case HPRT_SPEED_FULL: speed = TUSB_SPEED_FULL; break; case HPRT_SPEED_LOW : speed = TUSB_SPEED_LOW ; break; @@ -133,7 +134,8 @@ TU_ATTR_ALWAYS_INLINE static inline tusb_speed_t hprt_speed_get(dwc2_regs_t* dwc TU_ATTR_ALWAYS_INLINE static inline bool dma_host_enabled(const dwc2_regs_t* dwc2) { (void) dwc2; // Internal DMA only - return CFG_TUH_DWC2_DMA_ENABLE && dwc2->ghwcfg2_bm.arch == GHWCFG2_ARCH_INTERNAL_DMA; + const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; + return CFG_TUH_DWC2_DMA_ENABLE && ghwcfg2.arch == GHWCFG2_ARCH_INTERNAL_DMA; } #if CFG_TUH_MEM_DCACHE_ENABLE @@ -168,15 +170,18 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t channel_alloc(dwc2_regs_t* dwc2) { } // Check if is periodic (interrupt/isochronous) -TU_ATTR_ALWAYS_INLINE static inline bool edpt_is_periodic(uint8_t ep_type) { - return ep_type == HCCHAR_EPTYPE_INTERRUPT || ep_type == HCCHAR_EPTYPE_ISOCHRONOUS; +TU_ATTR_ALWAYS_INLINE static inline bool channel_is_periodic(uint32_t hcchar) { + const dwc2_channel_char_t hcchar_bm = {.value = hcchar}; + return hcchar_bm.ep_type == HCCHAR_EPTYPE_INTERRUPT || hcchar_bm.ep_type == HCCHAR_EPTYPE_ISOCHRONOUS; } TU_ATTR_ALWAYS_INLINE static inline uint8_t req_queue_avail(const dwc2_regs_t* dwc2, bool is_period) { if (is_period) { - return dwc2->hptxsts_bm.req_queue_available; + const dwc2_hptxsts_t hptxsts = {.value = dwc2->hptxsts}; + return hptxsts.req_queue_available; } else { - return dwc2->hnptxsts_bm.req_queue_available; + const dwc2_hnptxsts_t hnptxsts = {.value = dwc2->hnptxsts}; + return hnptxsts.req_queue_available; } } @@ -188,7 +193,7 @@ TU_ATTR_ALWAYS_INLINE static inline void channel_dealloc(dwc2_regs_t* dwc2, uint TU_ATTR_ALWAYS_INLINE static inline bool channel_disable(const dwc2_regs_t* dwc2, dwc2_channel_t* channel) { // disable also require request queue - TU_ASSERT(req_queue_avail(dwc2, edpt_is_periodic(channel->hcchar_bm.ep_type))); + TU_ASSERT(req_queue_avail(dwc2, channel_is_periodic(channel->hcchar))); channel->hcintmsk |= HCINT_HALTED; channel->hcchar |= HCCHAR_CHDIS | HCCHAR_CHENA; // must set both CHDIS and CHENA return true; @@ -196,7 +201,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool channel_disable(const dwc2_regs_t* dwc2 // attempt to send IN token to receive data TU_ATTR_ALWAYS_INLINE static inline bool channel_send_in_token(const dwc2_regs_t* dwc2, dwc2_channel_t* channel) { - TU_ASSERT(req_queue_avail(dwc2, edpt_is_periodic(channel->hcchar_bm.ep_type))); + TU_ASSERT(req_queue_avail(dwc2, channel_is_periodic(channel->hcchar))); channel->hcchar |= HCCHAR_CHENA; return true; } @@ -206,8 +211,8 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t channel_find_enabled(dwc2_regs_t* dw const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2); for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) { if (_hcd_data.xfer[ch_id].allocated) { - const dwc2_channel_char_t hcchar_bm = dwc2->channel[ch_id].hcchar_bm; - if (hcchar_bm.dev_addr == dev_addr && hcchar_bm.ep_num == ep_num && (ep_num == 0 || hcchar_bm.ep_dir == ep_dir)) { + const dwc2_channel_char_t hcchar = {.value = dwc2->channel[ch_id].hcchar}; + if (hcchar.dev_addr == dev_addr && hcchar.ep_num == ep_num && (ep_num == 0 || hcchar.ep_dir == ep_dir)) { return ch_id; } } @@ -304,12 +309,13 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t cal_next_pid(uint8_t pid, uint8_t pa static void dfifo_host_init(uint8_t rhport) { const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport]; dwc2_regs_t* dwc2 = DWC2_REG(rhport); + const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; // Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per channel const bool is_dma = dma_host_enabled(dwc2); uint16_t dfifo_top = dwc2_controller->ep_fifo_size/4; if (is_dma) { - dfifo_top -= dwc2->ghwcfg2_bm.num_host_ch; + dfifo_top -= ghwcfg2.num_host_ch; } // fixed allocation for now, improve later: @@ -319,7 +325,7 @@ static void dfifo_host_init(uint8_t rhport) { uint32_t ptx_largest = is_highspeed ? TUSB_EPSIZE_ISO_HS_MAX/4 : 256/4; uint16_t nptxfsiz = 2 * nptx_largest; - uint16_t rxfsiz = 2 * (ptx_largest + 2) + dwc2->ghwcfg2_bm.num_host_ch; + uint16_t rxfsiz = 2 * (ptx_largest + 2) + ghwcfg2.num_host_ch; TU_ASSERT(dfifo_top >= (nptxfsiz + rxfsiz),); uint16_t ptxfsiz = dfifo_top - (nptxfsiz + rxfsiz); @@ -509,10 +515,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* // clean up channel after part of transfer is done but the whole urb is not complete static void channel_xfer_out_wrapup(dwc2_regs_t* dwc2, uint8_t ch_id) { hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - dwc2_channel_t* channel = &dwc2->channel[ch_id]; + const dwc2_channel_t* channel = &dwc2->channel[ch_id]; hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; - edpt->next_pid = channel->hctsiz_bm.pid; // save PID + const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; + edpt->next_pid = hctsiz.pid; // save PID /* Since hctsiz.xfersize field reflects the number of bytes transferred via the AHB, not the USB) * For IN: we can use hctsiz.xfersize as remaining bytes. @@ -520,9 +527,10 @@ static void channel_xfer_out_wrapup(dwc2_regs_t* dwc2, uint8_t ch_id) { * number of packets that have been transferred via the USB. This is always an integral number of packets if the * transfer was halted before its normal completion. */ - const uint16_t remain_packets = channel->hctsiz_bm.packet_count; - const uint16_t total_packets = cal_packet_count(edpt->buflen, channel->hcchar_bm.ep_size); - const uint16_t actual_bytes = (total_packets - remain_packets) * channel->hcchar_bm.ep_size; + const uint16_t remain_packets = hctsiz.packet_count; + const dwc2_channel_char_t hcchar = {.value = channel->hcchar}; + const uint16_t total_packets = cal_packet_count(edpt->buflen, hcchar.ep_size); + const uint16_t actual_bytes = (total_packets - remain_packets) * hcchar.ep_size; xfer->fifo_bytes = 0; xfer->xferred_bytes += actual_bytes; @@ -535,7 +543,7 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; dwc2_channel_char_t* hcchar_bm = &edpt->hcchar_bm; dwc2_channel_t* channel = &dwc2->channel[ch_id]; - bool const is_period = edpt_is_periodic(hcchar_bm->ep_type); + bool const is_period = channel_is_periodic(hcchar_bm->ep_type); // clear previous state xfer->fifo_bytes = 0; @@ -548,12 +556,15 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { // hctsiz: zero length packet still count as 1 const uint16_t packet_count = cal_packet_count(edpt->buflen, hcchar_bm->ep_size); - uint32_t hctsiz = (edpt->next_pid << HCTSIZ_PID_Pos) | (packet_count << HCTSIZ_PKTCNT_Pos) | edpt->buflen; + dwc2_channel_tsize_t hctsiz = {.value = 0}; + hctsiz.pid = edpt->next_pid; // next PID is set in transfer complete interrupt + hctsiz.packet_count = packet_count; + hctsiz.xfer_size = edpt->buflen; if (edpt->do_ping && edpt->speed == TUSB_SPEED_HIGH && edpt->next_pid != HCTSIZ_PID_SETUP && hcchar_bm->ep_dir == TUSB_DIR_OUT) { - hctsiz |= HCTSIZ_DOPING; + hctsiz.do_ping = 1; } - channel->hctsiz = hctsiz; + channel->hctsiz = hctsiz.value; edpt->do_ping = 0; // pre-calculate next PID based on packet count, adjusted in transfer complete interrupt if short packet @@ -699,13 +710,16 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci dwc2_channel_t* channel = &dwc2->channel[ch_id]; hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; - if (edpt_is_periodic(channel->hcchar_bm.ep_type)){ + if (channel_is_periodic(channel->hcchar)){ + const dwc2_channel_split_t hcsplt = {.value = channel->hcsplt}; // retry immediately for periodic split NYET if we haven't reach max retry - if (channel->hcsplt_bm.split_en && channel->hcsplt_bm.split_compl && (hcint & HCINT_NYET || xfer->halted_nyet)) { + if (hcsplt.split_en && hcsplt.split_compl && (hcint & HCINT_NYET || xfer->halted_nyet)) { xfer->period_split_nyet_count++; xfer->halted_nyet = 0; if (xfer->period_split_nyet_count < HCD_XFER_PERIOD_SPLIT_NYET_MAX) { - channel->hcchar_bm.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame + dwc2_channel_char_t hcchar = {.value = channel->hcchar}; + hcchar.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame + channel->hcchar = hcchar.value; channel_send_in_token(dwc2, channel); return; } else { @@ -715,7 +729,8 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci } // for periodic, de-allocate channel, enable SOF set frame counter for later transfer - edpt->next_pid = channel->hctsiz_bm.pid; // save PID + const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; + edpt->next_pid = hctsiz.pid; // save PID edpt->uframe_countdown = edpt->uframe_interval; dwc2->gintmsk |= GINTSTS_SOF; @@ -756,13 +771,13 @@ static void handle_rxflvl_irq(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); // Pop control word off FIFO - const dwc2_grxstsp_t grxstsp_bm = dwc2->grxstsp_bm; - const uint8_t ch_id = grxstsp_bm.ep_ch_num; + const dwc2_grxstsp_t grxstsp = {.value= dwc2->grxstsp}; + const uint8_t ch_id = grxstsp.ep_ch_num; - switch (grxstsp_bm.packet_status) { + switch (grxstsp.packet_status) { case GRXSTS_PKTSTS_RX_DATA: { // In packet received, pop this entry --> ACK interrupt - const uint16_t byte_count = grxstsp_bm.byte_count; + const uint16_t byte_count = grxstsp.byte_count; hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,); hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; @@ -796,25 +811,26 @@ static void handle_rxflvl_irq(uint8_t rhport) { // return true if there is still pending data and need more ISR static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) { // Use period txsts for both p/np to get request queue space available (1-bit difference, it is small enough) - volatile dwc2_hptxsts_t* txsts_bm = (volatile dwc2_hptxsts_t*) (is_periodic ? &dwc2->hptxsts : &dwc2->hnptxsts); + const dwc2_hptxsts_t txsts = {.value = (is_periodic ? dwc2->hptxsts : dwc2->hnptxsts)}; const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2); for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) { dwc2_channel_t* channel = &dwc2->channel[ch_id]; + const dwc2_channel_char_t hcchar = {.value = channel->hcchar}; // skip writing to FIFO if channel is expecting halted. - if (!(channel->hcintmsk & HCINT_HALTED) && (channel->hcchar_bm.ep_dir == TUSB_DIR_OUT)) { + if (!(channel->hcintmsk & HCINT_HALTED) && (hcchar.ep_dir == TUSB_DIR_OUT)) { hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX); hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; - - const uint16_t remain_packets = channel->hctsiz_bm.packet_count; + const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; + const uint16_t remain_packets = hctsiz.packet_count; for (uint16_t i = 0; i < remain_packets; i++) { const uint16_t remain_bytes = edpt->buflen - xfer->fifo_bytes; - const uint16_t xact_bytes = tu_min16(remain_bytes, channel->hcchar_bm.ep_size); + const uint16_t xact_bytes = tu_min16(remain_bytes, hcchar.ep_size); // skip if there is not enough space in FIFO and RequestQueue. // Packet's last word written to FIFO will trigger a request queue - if ((xact_bytes > (txsts_bm->fifo_available << 2)) || (txsts_bm->req_queue_available == 0)) { + if ((xact_bytes > (txsts.fifo_available << 2)) || (txsts.req_queue_available == 0)) { return true; } @@ -831,23 +847,27 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; dwc2_channel_t* channel = &dwc2->channel[ch_id]; hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; + const dwc2_channel_char_t hcchar = {.value = channel->hcchar}; + dwc2_channel_split_t hcsplt = {.value = channel->hcsplt}; + const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; bool is_done = false; - // if (channel->hcsplt_bm.split_en) { + // if (hcsplt.split_en) { // if (edpt->hcchar_bm.ep_num == 1) { - // TU_LOG1("Frame %u, ch %u: ep %u, hcint 0x%04lX ", dwc2->hfnum_bm.num, ch_id, channel->hcchar_bm.ep_num, hcint); + // TU_LOG1("Frame %u, ch %u: ep %u, hcint 0x%04lX ", dwc2->hfnum_bm.num, ch_id, hcsplt.ep_num, hcint); // print_hcint(hcint); // } if (hcint & HCINT_XFER_COMPLETE) { if (edpt->hcchar_bm.ep_num != 0) { - edpt->next_pid = channel->hctsiz_bm.pid; // save pid (already toggled) + edpt->next_pid = hctsiz.pid; // save pid (already toggled) } - const uint16_t remain_packets = channel->hctsiz_bm.packet_count; - if (channel->hcsplt_bm.split_en && remain_packets && xfer->fifo_bytes == edpt->hcchar_bm.ep_size) { + const uint16_t remain_packets = hctsiz.packet_count; + if (hcsplt.split_en && remain_packets && xfer->fifo_bytes == edpt->hcchar_bm.ep_size) { // Split can only complete 1 transaction (up to 1 packet) at a time, schedule more - channel->hcsplt_bm.split_compl = 0; + hcsplt.split_compl = 0; + channel->hcsplt = hcsplt.value; } else { xfer->result = XFER_RESULT_SUCCESS; } @@ -866,34 +886,38 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h channel_disable(dwc2, channel); } else if (hcint & HCINT_NYET) { // restart complete split - channel->hcsplt_bm.split_compl = 1; + hcsplt.split_compl = 1; + channel->hcsplt = hcsplt.value; xfer->halted_nyet = 1; channel_disable(dwc2, channel); } else if (hcint & HCINT_NAK) { // NAK received, re-enable channel if request queue is available - if (channel->hcsplt_bm.split_en) { - channel->hcsplt_bm.split_compl = 0; // restart with start-split + if (hcsplt.split_en) { + hcsplt.split_compl = 0; // restart with start-split + channel->hcsplt = hcsplt.value; } channel_disable(dwc2, channel); } else if (hcint & HCINT_ACK) { xfer->err_count = 0; - if (channel->hcsplt_bm.split_en) { - if (!channel->hcsplt_bm.split_compl) { + if (hcsplt.split_en) { + if (!hcsplt.split_compl) { // start split is ACK --> do complete split channel->hcintmsk |= HCINT_NYET; - channel->hcsplt_bm.split_compl = 1; + hcsplt.split_compl = 1; + channel->hcsplt = hcsplt.value; channel_send_in_token(dwc2, channel); } else { // do nothing for complete split with DATA, this will trigger XferComplete and handled there } } else { // ACK with data - const uint16_t remain_packets = channel->hctsiz_bm.packet_count; + const uint16_t remain_packets = hctsiz.packet_count; if (remain_packets) { // still more packet to receive, also reset to start split - channel->hcsplt_bm.split_compl = 0; + hcsplt.split_compl = 0; + channel->hcsplt = hcsplt.value; channel_send_in_token(dwc2, channel); } } @@ -922,6 +946,7 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; dwc2_channel_t* channel = &dwc2->channel[ch_id]; hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; + dwc2_channel_split_t hcsplt = {.value = channel->hcsplt}; bool is_done = false; if (hcint & HCINT_XFER_COMPLETE) { @@ -933,9 +958,10 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t channel_disable(dwc2, channel); } else if (hcint & HCINT_NYET) { xfer->err_count = 0; - if (channel->hcsplt_bm.split_en) { + if (hcsplt.split_en) { // retry complete split - channel->hcsplt_bm.split_compl = 1; + hcsplt.split_compl = 1; + channel->hcsplt = hcsplt.value; channel->hcchar |= HCCHAR_CHENA; } else { edpt->do_ping = 1; @@ -968,9 +994,10 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t } else if (hcint & HCINT_ACK) { xfer->err_count = 0; channel->hcintmsk &= ~HCINT_ACK; - if (channel->hcsplt_bm.split_en && !channel->hcsplt_bm.split_compl) { + if (hcsplt.split_en && !hcsplt.split_compl) { // start split is ACK --> do complete split - channel->hcsplt_bm.split_compl = 1; + hcsplt.split_compl = 1; + channel->hcsplt = hcsplt.value; channel->hcchar |= HCCHAR_CHENA; } } @@ -989,6 +1016,9 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; dwc2_channel_t* channel = &dwc2->channel[ch_id]; hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; + dwc2_channel_char_t hcchar = {.value = channel->hcchar}; + dwc2_channel_split_t hcsplt = {.value = channel->hcsplt}; + const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; bool is_done = false; @@ -996,8 +1026,8 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci if (hcint & HCINT_HALTED) { if (hcint & (HCINT_XFER_COMPLETE | HCINT_STALL | HCINT_BABBLE_ERR)) { - const uint16_t remain_bytes = (uint16_t) channel->hctsiz_bm.xfer_size; - const uint16_t remain_packets = channel->hctsiz_bm.packet_count; + const uint16_t remain_bytes = (uint16_t) hctsiz.xfer_size; + const uint16_t remain_packets = hctsiz.packet_count; const uint16_t actual_len = edpt->buflen - remain_bytes; xfer->xferred_bytes += actual_len; @@ -1007,13 +1037,14 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci xfer->result = XFER_RESULT_STALLED; } else if (hcint & HCINT_BABBLE_ERR) { xfer->result = XFER_RESULT_FAILED; - } else if (channel->hcsplt_bm.split_en && remain_packets && actual_len == edpt->hcchar_bm.ep_size) { + } else if (hcsplt.split_en && remain_packets && actual_len == hcchar.ep_size) { // Split can only complete 1 transaction (up to 1 packet) at a time, schedule more is_done = false; edpt->buffer += actual_len; edpt->buflen -= actual_len; - channel->hcsplt_bm.split_compl = 0; + hcsplt.split_compl = 0; + channel->hcsplt = hcsplt.value; channel_xfer_in_retry(dwc2, ch_id, hcint); } else { xfer->result = XFER_RESULT_SUCCESS; @@ -1028,33 +1059,38 @@ static bool handle_channel_in_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci xfer->result = XFER_RESULT_FAILED; } else { channel->hcintmsk |= HCINT_ACK | HCINT_NAK | HCINT_DATATOGGLE_ERR; - channel->hcsplt_bm.split_compl = 0; + hcsplt.split_compl = 0; + channel->hcsplt = hcsplt.value; channel_xfer_in_retry(dwc2, ch_id, hcint); } } else if (hcint & HCINT_NYET) { // Must handle nyet before nak or ack. Could get a nyet at the same time as either of those on a BULK/CONTROL // OUT that started with a PING. The nyet takes precedence. - if (channel->hcsplt_bm.split_en) { + if (hcsplt.split_en) { // split not yet mean hub has no data, retry complete split - channel->hcsplt_bm.split_compl = 1; + hcsplt.split_compl = 1; + channel->hcsplt = hcsplt.value; channel_xfer_in_retry(dwc2, ch_id, hcint); } } else if (hcint & HCINT_ACK) { xfer->err_count = 0; channel->hcintmsk &= ~HCINT_ACK; - if (channel->hcsplt_bm.split_en) { + if (hcsplt.split_en) { // start split is ACK --> do complete split // TODO: for ISO must use xact_pos to plan complete split based on microframe (up to 187.5 bytes/uframe) - channel->hcsplt_bm.split_compl = 1; - if (edpt_is_periodic(channel->hcchar_bm.ep_type)) { - channel->hcchar_bm.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame + hcsplt.split_compl = 1; + channel->hcsplt = hcsplt.value; + if (channel_is_periodic(channel->hcchar)) { + hcchar.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame + channel->hcchar = hcchar.value; } channel_send_in_token(dwc2, channel); } } else if (hcint & (HCINT_NAK | HCINT_DATATOGGLE_ERR)) { xfer->err_count = 0; channel->hcintmsk &= ~(HCINT_NAK | HCINT_DATATOGGLE_ERR); - channel->hcsplt_bm.split_compl = 0; // restart with start-split + hcsplt.split_compl = 0; // restart with start-split + channel->hcsplt = hcsplt.value; channel_xfer_in_retry(dwc2, ch_id, hcint); } else if (hcint & HCINT_FARME_OVERRUN) { // retry start-split in next binterval @@ -1069,6 +1105,8 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; dwc2_channel_t* channel = &dwc2->channel[ch_id]; hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; + const dwc2_channel_char_t hcchar = {.value = channel->hcchar}; + dwc2_channel_split_t hcsplt = {.value = channel->hcsplt}; bool is_done = false; @@ -1104,16 +1142,18 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc } } } else if (hcint & HCINT_NYET) { - if (channel->hcsplt_bm.split_en && channel->hcsplt_bm.split_compl) { + if (hcsplt.split_en && hcsplt.split_compl) { // split not yet mean hub has no data, retry complete split - channel->hcsplt_bm.split_compl = 1; + hcsplt.split_compl = 1; + channel->hcsplt = hcsplt.value; channel->hcchar |= HCCHAR_CHENA; } } else if (hcint & HCINT_ACK) { xfer->err_count = 0; - if (channel->hcsplt_bm.split_en && !channel->hcsplt_bm.split_compl) { + if (hcsplt.split_en && !hcsplt.split_compl) { // start split is ACK --> do complete split - channel->hcsplt_bm.split_compl = 1; + hcsplt.split_compl = 1; + channel->hcsplt = hcsplt.value; channel->hcchar |= HCCHAR_CHENA; } } @@ -1136,7 +1176,7 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) { dwc2_channel_t* channel = &dwc2->channel[ch_id]; hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; TU_ASSERT(xfer->ep_id < CFG_TUH_DWC2_ENDPOINT_MAX,); - dwc2_channel_char_t hcchar_bm = channel->hcchar_bm; + dwc2_channel_char_t hcchar = {.value = channel->hcchar}; const uint32_t hcint = channel->hcint; channel->hcint = hcint; // clear interrupt @@ -1144,7 +1184,7 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) { bool is_done = false; if (is_dma) { #if CFG_TUH_DWC2_DMA_ENABLE - if (hcchar_bm.ep_dir == TUSB_DIR_OUT) { + if (hcchar.ep_dir == TUSB_DIR_OUT) { is_done = handle_channel_out_dma(dwc2, ch_id, hcint); } else { is_done = handle_channel_in_dma(dwc2, ch_id, hcint); @@ -1156,7 +1196,7 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) { #endif } else { #if CFG_TUH_DWC2_SLAVE_ENABLE - if (hcchar_bm.ep_dir == TUSB_DIR_OUT) { + if (hcchar.ep_dir == TUSB_DIR_OUT) { is_done = handle_channel_out_slave(dwc2, ch_id, hcint); } else { is_done = handle_channel_in_slave(dwc2, ch_id, hcint); @@ -1165,8 +1205,8 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) { } if (is_done) { - const uint8_t ep_addr = tu_edpt_addr(hcchar_bm.ep_num, hcchar_bm.ep_dir); - hcd_event_xfer_complete(hcchar_bm.dev_addr, ep_addr, xfer->xferred_bytes, xfer->result, in_isr); + const uint8_t ep_addr = tu_edpt_addr(hcchar.ep_num, hcchar.ep_dir); + hcd_event_xfer_complete(hcchar.dev_addr, ep_addr, xfer->xferred_bytes, (xfer_result_t)xfer->result, in_isr); channel_dealloc(dwc2, ch_id); } } @@ -1185,7 +1225,7 @@ static bool handle_sof_irq(uint8_t rhport, bool in_isr) { for(uint8_t ep_id = 0; ep_id < CFG_TUH_DWC2_ENDPOINT_MAX; ep_id++) { hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id]; - if (edpt->hcchar_bm.enable && edpt_is_periodic(edpt->hcchar_bm.ep_type) && edpt->uframe_countdown > 0) { + if (edpt->hcchar_bm.enable && channel_is_periodic(edpt->hcchar) && edpt->uframe_countdown > 0) { edpt->uframe_countdown -= tu_min32(ucount, edpt->uframe_countdown); if (edpt->uframe_countdown == 0) { if (!edpt_xfer_kickoff(dwc2, ep_id)) { @@ -1204,10 +1244,10 @@ static bool handle_sof_irq(uint8_t rhport, bool in_isr) { static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) { uint32_t hcfg = dwc2->hcfg & ~HCFG_FSLS_PHYCLK_SEL; - const dwc2_gusbcfg_t gusbcfg_bm = dwc2->gusbcfg_bm; + const dwc2_gusbcfg_t gusbcfg = {.value = dwc2->gusbcfg}; uint32_t phy_clock; - if (gusbcfg_bm.phy_sel) { + if (gusbcfg.phy_sel) { phy_clock = 48; // dedicated FS is 48Mhz if (speed == TUSB_SPEED_LOW) { hcfg |= HCFG_FSLS_PHYCLK_SEL_6MHZ; @@ -1215,11 +1255,11 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) { hcfg |= HCFG_FSLS_PHYCLK_SEL_48MHZ; } } else { - if (gusbcfg_bm.ulpi_utmi_sel) { + if (gusbcfg.ulpi_utmi_sel) { phy_clock = 60; // ULPI 8-bit is 60Mhz } else { // UTMI+ 16-bit is 30Mhz, 8-bit is 60Mhz - phy_clock = gusbcfg_bm.phy_if16 ? 30 : 60; + phy_clock = gusbcfg.phy_if16 ? 30 : 60; // Enable UTMI+ low power mode 48Mhz external clock if not highspeed if (speed == TUSB_SPEED_HIGH) { @@ -1252,7 +1292,7 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) { static void handle_hprt_irq(uint8_t rhport, bool in_isr) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint32_t hprt = dwc2->hprt & ~HPRT_W1_MASK; - const dwc2_hprt_t hprt_bm = dwc2->hprt_bm; + const dwc2_hprt_t hprt_bm = {.value = hprt}; if (dwc2->hprt & HPRT_CONN_DETECT) { // Port Connect Detect From 3acaffd64d4e14a984c6d1e0c36e733a825f319d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 8 Apr 2025 00:22:47 +0200 Subject: [PATCH 101/382] build fix. Signed-off-by: HiFiPhile --- hw/bsp/broadcom_32bit/family.cmake | 2 +- hw/bsp/broadcom_32bit/family.mk | 2 +- hw/bsp/broadcom_64bit/family.cmake | 2 +- hw/bsp/broadcom_64bit/family.mk | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/bsp/broadcom_32bit/family.cmake b/hw/bsp/broadcom_32bit/family.cmake index 5e57d8b1e..f1e8d12ff 100644 --- a/hw/bsp/broadcom_32bit/family.cmake +++ b/hw/bsp/broadcom_32bit/family.cmake @@ -42,7 +42,7 @@ function(add_board_target BOARD_TARGET) -ffreestanding -mgeneral-regs-only -fno-exceptions - -std=c17 + -std=gnu17 ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_DIR} diff --git a/hw/bsp/broadcom_32bit/family.mk b/hw/bsp/broadcom_32bit/family.mk index a282e9961..6acdf1197 100644 --- a/hw/bsp/broadcom_32bit/family.mk +++ b/hw/bsp/broadcom_32bit/family.mk @@ -10,7 +10,7 @@ CFLAGS += \ -nostartfiles \ -mgeneral-regs-only \ -fno-exceptions \ - -std=c17 + -std=gnu17 CROSS_COMPILE = arm-none-eabi- diff --git a/hw/bsp/broadcom_64bit/family.cmake b/hw/bsp/broadcom_64bit/family.cmake index 1a088c2c0..16f8e1eae 100644 --- a/hw/bsp/broadcom_64bit/family.cmake +++ b/hw/bsp/broadcom_64bit/family.cmake @@ -43,7 +43,7 @@ function(add_board_target BOARD_TARGET) -ffreestanding -mgeneral-regs-only -fno-exceptions - -std=c17 + -std=gnu17 ) target_compile_definitions(${BOARD_TARGET} PUBLIC BCM_VERSION=${BCM_VERSION} diff --git a/hw/bsp/broadcom_64bit/family.mk b/hw/bsp/broadcom_64bit/family.mk index 37d381f9f..92b5f69a3 100644 --- a/hw/bsp/broadcom_64bit/family.mk +++ b/hw/bsp/broadcom_64bit/family.mk @@ -9,7 +9,7 @@ CFLAGS += \ -nostartfiles \ --specs=nosys.specs \ -mgeneral-regs-only \ - -std=c17 + -std=gnu17 CROSS_COMPILE = aarch64-none-elf- From 2aff61ccb3797b85b99d6a1f3c3fb04a52f0d4fc Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 9 Apr 2025 19:40:03 +0200 Subject: [PATCH 102/382] Fix CI. Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index af17bb59a..f3dc23b9c 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -847,7 +847,6 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; dwc2_channel_t* channel = &dwc2->channel[ch_id]; hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; - const dwc2_channel_char_t hcchar = {.value = channel->hcchar}; dwc2_channel_split_t hcsplt = {.value = channel->hcsplt}; const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; bool is_done = false; From 72357cdb20ee7dca5a19d02ce9b7f14d237fb29e Mon Sep 17 00:00:00 2001 From: Maxime Vincent Date: Fri, 11 Apr 2025 12:15:56 +0200 Subject: [PATCH 103/382] dwc2/host: HFIR: Fix timing off-by-one --- src/portable/synopsys/dwc2/hcd_dwc2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 7cbef05b7..6f7551ed7 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -1242,9 +1242,9 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) { uint32_t hfir = dwc2->hfir & ~HFIR_FRIVL_Msk; if (speed == TUSB_SPEED_HIGH) { - hfir |= 125*phy_clock; + hfir |= 125*phy_clock - 1; // The "- 1" is the correct value. The Synopsys databook was corrected in 3.30a } else { - hfir |= 1000*phy_clock; + hfir |= 1000*phy_clock - 1; } dwc2->hfir = hfir; From 2064ee470d6c7b434d6b3aafe017ed60c3b17ab5 Mon Sep 17 00:00:00 2001 From: Maxime Vincent Date: Fri, 11 Apr 2025 12:14:07 +0200 Subject: [PATCH 104/382] dwc2/host: attach debouncing fixes --- src/host/usbh.c | 2 +- src/portable/synopsys/dwc2/hcd_dwc2.c | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index e60db53da..4b0f4d488 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1038,7 +1038,7 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) // Check if dev0 is removed if ((event->rhport == _dev0.rhport) && (event->connection.hub_addr == _dev0.hub_addr) && (event->connection.hub_port == _dev0.hub_port)) { - _dev0.enumerating = 0; + //_dev0.enumerating = 0;// Causes assert in dwc2 process_enumeration() -> ENUM_ADDR0_DEVICE_DESC } break; diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 7cbef05b7..65288e30c 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -109,6 +109,7 @@ typedef struct { typedef struct { hcd_xfer_t xfer[DWC2_CHANNEL_COUNT_MAX]; hcd_endpoint_t edpt[CFG_TUH_DWC2_ENDPOINT_MAX]; + bool attach_debounce; // if true: wait for the debounce delay before issuing new attach events } hcd_data_t; hcd_data_t _hcd_data; @@ -413,6 +414,11 @@ uint32_t hcd_frame_number(uint8_t rhport) { // Get the current connect status of roothub port bool hcd_port_connect_status(uint8_t rhport) { + // this is called from enum_new_device() - after the debouncing delays + if (_hcd_data.attach_debounce) { + _hcd_data.attach_debounce = false; // allow new attach events again + } + dwc2_regs_t* dwc2 = DWC2_REG(rhport); return dwc2->hprt & HPRT_CONN_STATUS; } @@ -1265,9 +1271,10 @@ static void handle_hprt_irq(uint8_t rhport, bool in_isr) { hprt |= HPRT_CONN_DETECT; if (hprt_bm.conn_status) { - hcd_event_device_attach(rhport, in_isr); - } else { - hcd_event_device_remove(rhport, in_isr); + if (!_hcd_data.attach_debounce) { + _hcd_data.attach_debounce = true; // block new attach events until the debounce delay is over + hcd_event_device_attach(rhport, in_isr); + } } } @@ -1330,6 +1337,19 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { handle_channel_irq(rhport, in_isr); } + if (gintsts & GINTSTS_DISCINT) { + // Device disconnected + dwc2->gintsts = GINTSTS_DISCINT; + + // ignore device removal if attach debounce is active + // it will evaluate the port status after the debounce delay + if (!_hcd_data.attach_debounce) { + if (!(dwc2->hprt & HPRT_CONN_STATUS)) { + hcd_event_device_remove(rhport, in_isr); + } + } + } + #if CFG_TUH_DWC2_SLAVE_ENABLE // RxFIFO non-empty interrupt handling if (gintsts & GINTSTS_RXFLVL) { From 925010fd841c5442579c503a3b1aa211cc25e8b2 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 11 Apr 2025 17:02:42 +0200 Subject: [PATCH 105/382] host/dwc2: resume OUT transfer when PING ACKed Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 7cbef05b7..22f3bc70a 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -590,7 +590,7 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { hcintmsk |= HCINT_BABBLE_ERR | HCINT_DATATOGGLE_ERR | HCINT_ACK; } else { hcintmsk |= HCINT_NYET; - if (edpt->hcsplt_bm.split_en) { + if (edpt->hcsplt_bm.split_en || hctsiz & HCTSIZ_DOPING) { hcintmsk |= HCINT_ACK; } } @@ -973,10 +973,17 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t } else if (hcint & HCINT_ACK) { xfer->err_count = 0; channel->hcintmsk &= ~HCINT_ACK; - if (channel->hcsplt_bm.split_en && !channel->hcsplt_bm.split_compl) { - // start split is ACK --> do complete split - channel->hcsplt_bm.split_compl = 1; - channel->hcchar |= HCCHAR_CHENA; + if (channel->hcsplt_bm.split_en) { + if(!channel->hcsplt_bm.split_compl) { + // start split is ACK --> do complete split + channel->hcsplt_bm.split_compl = 1; + channel->hcchar |= HCCHAR_CHENA; + } + } else { + // Device is ready, resume transfer + edpt->do_ping = 0; + xfer->err_count = 0; + TU_ASSERT(channel_xfer_start(dwc2, ch_id)); } } From 937b07cdc0bb9341db35b4d8444827b03d06e84a Mon Sep 17 00:00:00 2001 From: Patrick Plenefisch Date: Fri, 11 Apr 2025 18:19:39 -0400 Subject: [PATCH 106/382] Fix version string to actually be the version --- src/tusb_option.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tusb_option.h b/src/tusb_option.h index 29fdcb0d6..98f1a91b5 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -35,7 +35,7 @@ #define TUSB_VERSION_REVISION 0 #define TUSB_VERSION_NUMBER (TUSB_VERSION_MAJOR * 10000 + TUSB_VERSION_MINOR * 100 + TUSB_VERSION_REVISION) -#define TUSB_VERSION_STRING TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION) +#define TUSB_VERSION_STRING TU_XSTRING(TUSB_VERSION_MAJOR) "." TU_XSTRING(TUSB_VERSION_MINOR) "." TU_XSTRING(TUSB_VERSION_REVISION) //--------------------------------------------------------------------+ // Supported MCUs From aecfd3433c6c235d632636f2936c7df180e9d12a Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 12 Apr 2025 13:36:10 +0200 Subject: [PATCH 107/382] Fix handle_hprt_irq Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index f3dc23b9c..3acdf580d 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -1290,10 +1290,10 @@ static void port0_enable(dwc2_regs_t* dwc2, tusb_speed_t speed) { */ static void handle_hprt_irq(uint8_t rhport, bool in_isr) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - uint32_t hprt = dwc2->hprt & ~HPRT_W1_MASK; - const dwc2_hprt_t hprt_bm = {.value = hprt}; + const dwc2_hprt_t hprt_bm = {.value = dwc2->hprt}; + uint32_t hprt = hprt_bm.value & ~HPRT_W1_MASK; - if (dwc2->hprt & HPRT_CONN_DETECT) { + if (hprt_bm.conn_detected) { // Port Connect Detect hprt |= HPRT_CONN_DETECT; @@ -1304,7 +1304,7 @@ static void handle_hprt_irq(uint8_t rhport, bool in_isr) { } } - if (dwc2->hprt & HPRT_ENABLE_CHANGE) { + if (hprt_bm.enable_change) { // Port enable change hprt |= HPRT_ENABLE_CHANGE; From af0c47e06ec079ffa80ea55ff5de58c08ac1e750 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 12 Apr 2025 15:21:19 +0200 Subject: [PATCH 108/382] Fix typo Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 3acdf580d..8f1103415 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -543,7 +543,7 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; dwc2_channel_char_t* hcchar_bm = &edpt->hcchar_bm; dwc2_channel_t* channel = &dwc2->channel[ch_id]; - bool const is_period = channel_is_periodic(hcchar_bm->ep_type); + bool const is_period = channel_is_periodic(edpt->hcchar); // clear previous state xfer->fifo_bytes = 0; From 7f246d4b762d24feedcfbfc2ce3d37cf8ed5abc6 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 9 Apr 2025 21:33:22 +0200 Subject: [PATCH 109/382] Fix swo logger case. Signed-off-by: HiFiPhile --- hw/bsp/family_support.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index e7161eba3..bf0f0566d 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -208,9 +208,10 @@ function(family_configure_common TARGET RTOS) # LOGGER option if (DEFINED LOGGER) + string(TOUPPER ${LOGGER} LOGGER) target_compile_definitions(${TARGET} PUBLIC LOGGER_${LOGGER}) # Add segger rtt to example - if(LOGGER STREQUAL "RTT" OR LOGGER STREQUAL "rtt") + if(LOGGER STREQUAL "RTT") target_sources(${TARGET} PUBLIC ${TOP}/lib/SEGGER_RTT/RTT/SEGGER_RTT.c) target_include_directories(${TARGET} PUBLIC ${TOP}/lib/SEGGER_RTT/RTT) # target_compile_definitions(${TARGET} PUBLIC SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) From b4a762dd581a7393a4658e6387398a0a2bd69d17 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 12 Apr 2025 17:01:10 +0200 Subject: [PATCH 110/382] Fix RTT buffer not detected. Signed-off-by: HiFiPhile --- .../boards/stm32h7s3nucleo/board.cmake | 6 + .../stm32h7rs/boards/stm32h7s3nucleo/board.mk | 7 + .../stm32h7s3nucleo/stm32h7s3xx_flash.icf | 55 +++++ .../stm32h7s3nucleo/stm32h7s3xx_flash.ld | 209 ++++++++++++++++++ hw/bsp/stm32h7rs/family.mk | 2 +- 5 files changed, 278 insertions(+), 1 deletion(-) create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf create mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake index 7891618e2..16cb77ff4 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake @@ -2,8 +2,14 @@ set(MCU_VARIANT stm32h7s3xx) set(JLINK_DEVICE stm32h7s3xx) function(update_board TARGET) + + set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stm32h7s3xx_flash.ld) + set(LD_FILE_Clang ${LD_FILE_GNU}) + set(LD_FILE_IAR ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stm32h7s3xx_flash.icf) + target_compile_definitions(${TARGET} PUBLIC STM32H7S3xx + SEGGER_RTT_SECTION="noncacheable_buffer" ) target_sources(${TARGET} PUBLIC diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk index f0dfe01dc..c802d0211 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk @@ -7,9 +7,16 @@ JLINK_DEVICE = stm32h7s3xx # flash target using on-board stlink flash: flash-stlink +# Linker +LD_FILE_GCC = $(BOARD_PATH)/stm32h7s3xx_flash.ld +LD_FILE_IAR = $(BOARD_PATH)/stm32h7s3xx_flash.icf + SRC_C += \ $(BOARD_PATH)/tcpp0203/tcpp0203.c \ $(BOARD_PATH)/tcpp0203/tcpp0203_reg.c \ INC += \ $(TOP)/$(BOARD_PATH)/tcpp0203 \ + +CFLAGS += \ + -DSEGGER_RTT_SECTION=\"noncacheable_buffer\" \ diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf new file mode 100644 index 000000000..17af9a620 --- /dev/null +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf @@ -0,0 +1,55 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +define symbol __ICFEDIT_intvec_start__ = 0x08000000; +/*-Memory Regions-*/ +define symbol NONCACHEABLEBUFFER_size = 0x1000; +define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; +define symbol __ICFEDIT_region_ROM_end__ = 0x0800FFFF; +define symbol __ICFEDIT_region_RAM_start__ = 0x24000000; +define symbol __ICFEDIT_region_RAM_end__ = 0x2404FFFF - NONCACHEABLEBUFFER_size; +define symbol NONCACHEABLEBUFFER_start = __ICFEDIT_region_RAM_end__ + 1; +define symbol NONCACHEABLEBUFFER_end = __ICFEDIT_region_RAM_end__ + NONCACHEABLEBUFFER_size; + + +/*-Sizes-*/ +define symbol __ICFEDIT_size_cstack__ = 0x800; +define symbol __ICFEDIT_size_heap__ = 0x200; +/**** End of ICF editor section. ###ICF###*/ + +define symbol __region_ITCM_start__ = 0x00000000; +define symbol __region_ITCM_end__ = 0x0000FFFF; +define symbol __region_DTCM_start__ = 0x20000000; +define symbol __region_DTCM_end__ = 0x2000FFFF; +define symbol __region_SRAMAHB_start__ = 0x30000000; +define symbol __region_SRAMAHB_end__ = 0x30007FFF; +define symbol __region_BKPSRAM_start__ = 0x38800000; +define symbol __region_BKPSRAM_end__ = 0x38800FFF; + +export symbol NONCACHEABLEBUFFER_start; +export symbol NONCACHEABLEBUFFER_size; + +export symbol __ICFEDIT_region_ROM_start__; +export symbol __ICFEDIT_region_ROM_end__; +define memory mem with size = 4G; +define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region NONCACHEABLE_region = mem:[from NONCACHEABLEBUFFER_start to NONCACHEABLEBUFFER_end]; +define region ITCM_region = mem:[from __region_ITCM_start__ to __region_ITCM_end__]; +define region DTCM_region = mem:[from __region_DTCM_start__ to __region_DTCM_end__]; +define region SRAMAHB_region = mem:[from __region_SRAMAHB_start__ to __region_SRAMAHB_end__]; +define region BKPSRAM_region = mem:[from __region_BKPSRAM_start__ to __region_BKPSRAM_end__]; + +define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; +define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; + +initialize by copy { readwrite }; +do not initialize { section .noinit }; + +place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; + +place in ROM_region { readonly }; +place in RAM_region { readwrite }; +place in NONCACHEABLE_region { section noncacheable_buffer }; +place in DTCM_region { block CSTACK, block HEAP }; diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld new file mode 100644 index 000000000..2c6bb27de --- /dev/null +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld @@ -0,0 +1,209 @@ +/* +****************************************************************************** +** +** @file : LinkerScript.ld +** +** @author : Auto-generated by STM32CubeIDE +** +** @brief : Linker script for STM32H7S3xx Device from STM32H7RS series +** 64Kbytes FLASH +** 456Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +****************************************************************************** +** @attention +** +** Copyright (c) 2023 STMicroelectronics. +** All rights reserved. +** +** This software is licensed under terms that can be found in the LICENSE file +** in the root directory of this software component. +** If no LICENSE file comes with this software, it is provided AS-IS. +** +****************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = ORIGIN(DTCM) + LENGTH(DTCM); /* end of "DTCM" Ram type memory */ + +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +__FLASH_BEGIN = 0x08000000; +__FLASH_SIZE = 0x00010000; + + +__RAM_BEGIN = 0x24000000; +__RAM_SIZE = 0x4FC00; +__RAM_NONCACHEABLEBUFFER_SIZE = 0x1000; + +/* Memories definition */ +MEMORY +{ + RAM (xrw) : ORIGIN = __RAM_BEGIN, LENGTH = __RAM_SIZE + RAM_NONCACHEABLEBUFFER (xrw) : ORIGIN = __RAM_BEGIN + __RAM_SIZE, LENGTH = __RAM_NONCACHEABLEBUFFER_SIZE + + ITCM (xrw) : ORIGIN = 0x00000000, LENGTH = 0x00010000 + DTCM (rw) : ORIGIN = 0x20000000, LENGTH = 0x00010000 + SRAMAHB (rw) : ORIGIN = 0x30000000, LENGTH = 0x00008000 + BKPSRAM (rw) : ORIGIN = 0x38800000, LENGTH = 0x00001000 + + FLASH (xrw) : ORIGIN = __FLASH_BEGIN, LENGTH = __FLASH_SIZE +} + +/* Sections */ +SECTIONS +{ + /* The startup code into "FLASH" Rom type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data into "FLASH" Rom type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data into "FLASH" Rom type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + + .ARM (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + + .init_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + + .fini_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> FLASH + + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + RW_NONCACHEABLE : + { + __NONCACHEABLEBUFFER_BEGIN = .;/* create symbol for start of section */ + KEEP(*(noncacheable_buffer)) + __NONCACHEABLEBUFFER_END = .; /* create symbol for start of section */ + } > RAM_NONCACHEABLEBUFFER + + /* User_heap_stack section, used to check that there is enough "DTCM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >DTCM + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/hw/bsp/stm32h7rs/family.mk b/hw/bsp/stm32h7rs/family.mk index e2d6d40e4..d679b72f1 100644 --- a/hw/bsp/stm32h7rs/family.mk +++ b/hw/bsp/stm32h7rs/family.mk @@ -88,5 +88,5 @@ SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_$(MCU_VARIANT).s SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT).s # Linker -LD_FILE_GCC = $(ST_CMSIS)/Source/Templates/gcc/linker/$(MCU_VARIANT)_flash.ld +LD_FILE_GCC ?= $(ST_CMSIS)/Source/Templates/gcc/linker/$(MCU_VARIANT)_flash.ld LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash.icf From 8b69dc32d4029e80aeddd8576ffe499e5f368a5b Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 12 Apr 2025 20:00:47 +0200 Subject: [PATCH 111/382] Increase RTT buffer size Signed-off-by: HiFiPhile --- hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake | 9 +++++---- hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk | 1 + .../boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf | 2 +- .../boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake index 16cb77ff4..ea9ffacf4 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake @@ -1,15 +1,16 @@ set(MCU_VARIANT stm32h7s3xx) set(JLINK_DEVICE stm32h7s3xx) -function(update_board TARGET) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/stm32h7s3xx_flash.ld) +set(LD_FILE_Clang ${LD_FILE_GNU}) +set(LD_FILE_IAR ${CMAKE_CURRENT_LIST_DIR}/stm32h7s3xx_flash.icf) - set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stm32h7s3xx_flash.ld) - set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/stm32h7s3xx_flash.icf) +function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC STM32H7S3xx SEGGER_RTT_SECTION="noncacheable_buffer" + BUFFER_SIZE_UP=0x3000 ) target_sources(${TARGET} PUBLIC diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk index c802d0211..1946f523c 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk @@ -20,3 +20,4 @@ INC += \ CFLAGS += \ -DSEGGER_RTT_SECTION=\"noncacheable_buffer\" \ + -DBUFFER_SIZE_UP=0x3000 \ diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf index 17af9a620..8ffaa74a7 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf @@ -4,7 +4,7 @@ /*-Specials-*/ define symbol __ICFEDIT_intvec_start__ = 0x08000000; /*-Memory Regions-*/ -define symbol NONCACHEABLEBUFFER_size = 0x1000; +define symbol NONCACHEABLEBUFFER_size = 0x4000; define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; define symbol __ICFEDIT_region_ROM_end__ = 0x0800FFFF; define symbol __ICFEDIT_region_RAM_start__ = 0x24000000; diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld index 2c6bb27de..a81763bf9 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld @@ -47,7 +47,7 @@ __FLASH_SIZE = 0x00010000; __RAM_BEGIN = 0x24000000; __RAM_SIZE = 0x4FC00; -__RAM_NONCACHEABLEBUFFER_SIZE = 0x1000; +__RAM_NONCACHEABLEBUFFER_SIZE = 0x4000; /* Memories definition */ MEMORY From c183108a82c394e35c9d61313ef3f78492e13fca Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 13 Apr 2025 12:24:30 +0200 Subject: [PATCH 112/382] Skip net_lwip_webserver, too big for h7rs Signed-off-by: HiFiPhile --- examples/device/net_lwip_webserver/skip.txt | 1 + hw/bsp/stm32h7rs/family.cmake | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index 5ebe71612..09fbf62c3 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -10,6 +10,7 @@ mcu:SAMD11 mcu:STM32L0 mcu:STM32F0 mcu:KINETIS_KL +mcu:STM32H7RS family:broadcom_64bit family:broadcom_32bit family:espressif diff --git a/hw/bsp/stm32h7rs/family.cmake b/hw/bsp/stm32h7rs/family.cmake index d55a897ad..61c3ebaea 100644 --- a/hw/bsp/stm32h7rs/family.cmake +++ b/hw/bsp/stm32h7rs/family.cmake @@ -14,7 +14,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) set(CMAKE_SYSTEM_CPU cortex-m7 CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) -set(FAMILY_MCUS STM32H7 CACHE INTERNAL "") +set(FAMILY_MCUS STM32H7RS CACHE INTERNAL "") # ---------------------- # Port & Speed Selection From d039d54a89d15b9d11f8f22f94279bedc8b28c09 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 14 Apr 2025 16:31:17 +0700 Subject: [PATCH 113/382] channge DWC2_CHANNEL_COUNT/DWC2_EP_COUNT to inline function --- hw/bsp/broadcom_32bit/family.cmake | 2 +- hw/bsp/broadcom_32bit/family.mk | 2 +- hw/bsp/broadcom_64bit/family.cmake | 2 +- hw/bsp/broadcom_64bit/family.mk | 2 +- src/portable/synopsys/dwc2/dcd_dwc2.c | 20 +- src/portable/synopsys/dwc2/dwc2_common.c | 2 +- src/portable/synopsys/dwc2/dwc2_type.h | 302 +++++++++++------------ src/portable/synopsys/dwc2/hcd_dwc2.c | 15 +- 8 files changed, 177 insertions(+), 170 deletions(-) diff --git a/hw/bsp/broadcom_32bit/family.cmake b/hw/bsp/broadcom_32bit/family.cmake index f1e8d12ff..5e57d8b1e 100644 --- a/hw/bsp/broadcom_32bit/family.cmake +++ b/hw/bsp/broadcom_32bit/family.cmake @@ -42,7 +42,7 @@ function(add_board_target BOARD_TARGET) -ffreestanding -mgeneral-regs-only -fno-exceptions - -std=gnu17 + -std=c17 ) target_include_directories(${BOARD_TARGET} PUBLIC ${SDK_DIR} diff --git a/hw/bsp/broadcom_32bit/family.mk b/hw/bsp/broadcom_32bit/family.mk index 6acdf1197..a282e9961 100644 --- a/hw/bsp/broadcom_32bit/family.mk +++ b/hw/bsp/broadcom_32bit/family.mk @@ -10,7 +10,7 @@ CFLAGS += \ -nostartfiles \ -mgeneral-regs-only \ -fno-exceptions \ - -std=gnu17 + -std=c17 CROSS_COMPILE = arm-none-eabi- diff --git a/hw/bsp/broadcom_64bit/family.cmake b/hw/bsp/broadcom_64bit/family.cmake index 16f8e1eae..1a088c2c0 100644 --- a/hw/bsp/broadcom_64bit/family.cmake +++ b/hw/bsp/broadcom_64bit/family.cmake @@ -43,7 +43,7 @@ function(add_board_target BOARD_TARGET) -ffreestanding -mgeneral-regs-only -fno-exceptions - -std=gnu17 + -std=c17 ) target_compile_definitions(${BOARD_TARGET} PUBLIC BCM_VERSION=${BCM_VERSION} diff --git a/hw/bsp/broadcom_64bit/family.mk b/hw/bsp/broadcom_64bit/family.mk index 92b5f69a3..37d381f9f 100644 --- a/hw/bsp/broadcom_64bit/family.mk +++ b/hw/bsp/broadcom_64bit/family.mk @@ -9,7 +9,7 @@ CFLAGS += \ -nostartfiles \ --specs=nosys.specs \ -mgeneral-regs-only \ - -std=gnu17 + -std=c17 CROSS_COMPILE = aarch64-none-elf- diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 83ebc18cb..52d675611 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -41,12 +41,6 @@ #include "device/dcd.h" #include "dwc2_common.h" -#if TU_CHECK_MCU(OPT_MCU_GD32VF103) - #define DWC2_EP_COUNT(_dwc2) DWC2_EP_MAX -#else - #define DWC2_EP_COUNT(_dwc2) ({const dwc2_ghwcfg2_t ghwcfg2 = {.value = (_dwc2)->ghwcfg2}; ghwcfg2.num_dev_ep + 1;}) -#endif - //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ @@ -79,6 +73,16 @@ CFG_TUD_MEM_SECTION static struct { TUD_EPBUF_DEF(setup_packet, 8); } _dcd_usbbuf; +TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc2) { + #if TU_CHECK_MCU(OPT_MCU_GD32VF103) + return DWC2_EP_MAX; + #else + const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; + return ghwcfg2.num_dev_ep + 1; + #endif +} + + //-------------------------------------------------------------------- // DMA //-------------------------------------------------------------------- @@ -629,7 +633,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { // 7.4.1 Initialization on USB Reset static void handle_bus_reset(uint8_t rhport) { dwc2_regs_t *dwc2 = DWC2_REG(rhport); - const uint8_t ep_count = DWC2_EP_COUNT(dwc2); + const uint8_t ep_count = dwc2_ep_count(dwc2); tu_memclr(xfer_status, sizeof(xfer_status)); @@ -926,7 +930,7 @@ static void handle_epin_dma(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepin static void handle_ep_irq(uint8_t rhport, uint8_t dir) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const bool is_dma = dma_device_enabled(dwc2); - const uint8_t ep_count = DWC2_EP_COUNT(dwc2); + const uint8_t ep_count = dwc2_ep_count(dwc2); const uint8_t daint_offset = (dir == TUSB_DIR_IN) ? DAINT_IEPINT_Pos : DAINT_OEPINT_Pos; dwc2_dep_t* ep_base = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][0]; diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 989a833ff..f6ed8fc98 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -173,7 +173,6 @@ static bool check_dwc2(dwc2_regs_t* dwc2) { //-------------------------------------------------------------------- bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role) { (void)dwc2; - const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; #if CFG_TUD_ENABLED if (role == TUSB_ROLE_DEVICE && !TUD_OPT_HIGH_SPEED) { return false; @@ -185,6 +184,7 @@ bool dwc2_core_is_highspeed(dwc2_regs_t* dwc2, tusb_role_t role) { } #endif + const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; return ghwcfg2.hs_phy_type != GHWCFG2_HSPHY_NOT_SUPPORTED; } diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 5ecf9d487..34e046346 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -299,17 +299,17 @@ TU_VERIFY_STATIC(sizeof(dwc2_gusbcfg_t) == 4, "incorrect size"); typedef union { uint32_t value; struct TU_ATTR_PACKED { - uint32_t core_soft_rst : 1; // 0 Core Soft Reset - uint32_t piufs_soft_rst : 1; // 1 PIU FS Dedicated Controller Soft Reset - uint32_t frame_counter_rst : 1; // 2 Frame Counter Reset (host) - uint32_t intoken_q_flush : 1; // 3 IN Token Queue Flush - uint32_t rx_fifo_flush : 1; // 4 RX FIFO Flush - uint32_t tx_fifo_flush : 1; // 5 TX FIFO Flush - uint32_t tx_fifo_num : 5; // 6..10 TX FIFO Number - uint32_t rsv11_28 :18; // 11..28 Reserved - uint32_t core_soft_rst_done : 1; // 29 Core Soft Reset Done, from v4.20a - uint32_t dma_req : 1; // 30 DMA Request - uint32_t ahb_idle : 1; // 31 AHB Idle + uint32_t core_soft_rst : 1; // 0 Core Soft Reset + uint32_t piufs_soft_rst : 1; // 1 PIU FS Dedicated Controller Soft Reset + uint32_t frame_counter_rst : 1; // 2 Frame Counter Reset (host) + uint32_t intoken_q_flush : 1; // 3 IN Token Queue Flush + uint32_t rx_fifo_flush : 1; // 4 RX FIFO Flush + uint32_t tx_fifo_flush : 1; // 5 TX FIFO Flush + uint32_t tx_fifo_num : 5; // 6..10 TX FIFO Number + uint32_t rsv11_28 :18; // 11..28 Reserved + uint32_t core_soft_rst_done : 1; // 29 Core Soft Reset Done, from v4.20a + uint32_t dma_req : 1; // 30 DMA Request + uint32_t ahb_idle : 1; // 31 AHB Idle }; } dwc2_grstctl_t; TU_VERIFY_STATIC(sizeof(dwc2_grstctl_t) == 4, "incorrect size"); @@ -317,12 +317,12 @@ TU_VERIFY_STATIC(sizeof(dwc2_grstctl_t) == 4, "incorrect size"); typedef union { uint32_t value; struct TU_ATTR_PACKED { - uint32_t ep_ch_num : 4; // 0..3 Endpoint/Channel Number - uint32_t byte_count :11; // 4..14 Byte Count - uint32_t dpid : 2; // 15..16 Data PID - uint32_t packet_status : 4; // 17..20 Packet Status - uint32_t frame_number : 4; // 21..24 Frame Number - uint32_t rsv25_31 : 7; // 25..31 Reserved + uint32_t ep_ch_num : 4; // 0..3 Endpoint/Channel Number + uint32_t byte_count :11; // 4..14 Byte Count + uint32_t dpid : 2; // 15..16 Data PID + uint32_t packet_status : 4; // 17..20 Packet Status + uint32_t frame_number : 4; // 21..24 Frame Number + uint32_t rsv25_31 : 7; // 25..31 Reserved }; } dwc2_grxstsp_t; TU_VERIFY_STATIC(sizeof(dwc2_grxstsp_t) == 4, "incorrect size"); @@ -371,28 +371,28 @@ TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg3_t) == 4, "incorrect size"); typedef union { uint32_t value; struct TU_ATTR_PACKED { - uint32_t num_dev_period_in_ep : 4; // 0..3 Number of Device Periodic IN Endpoints - uint32_t partial_powerdown : 1; // 4 Partial Power Down Enabled - uint32_t ahb_freq_min : 1; // 5 1: minimum of AHB frequency is less than 60 MHz - uint32_t hibernation : 1; // 6 Hibernation feature is enabled - uint32_t extended_hibernation : 1; // 7 Extended Hibernation feature is enabled - uint32_t reserved8 : 1; // 8 Reserved - uint32_t enhanced_lpm_support1 : 1; // 9 Enhanced LPM Support1 - uint32_t service_interval_flow : 1; // 10 Service Interval flow is supported - uint32_t ipg_isoc_support : 1; // 11 Interpacket GAP ISO OUT worst-case is supported - uint32_t acg_support : 1; // 12 Active clock gating is supported - uint32_t enhanced_lpm_support : 1; // 13 Enhanced LPM Support - uint32_t phy_data_width : 2; // 14..15 0: 8 bits | 1: 16 bits | 2: 8/16 software selectable - uint32_t ctrl_ep_num : 4; // 16..19 Number of Device control endpoints in addition to EP0 - uint32_t iddg_filter : 1; // 20 IDDG Filter Enabled - uint32_t vbus_valid_filter : 1; // 21 VBUS Valid Filter Enabled - uint32_t a_valid_filter : 1; // 22 A Valid Filter Enabled - uint32_t b_valid_filter : 1; // 23 B Valid Filter Enabled - uint32_t session_end_filter : 1; // 24 Session End Filter Enabled - uint32_t dedicated_fifos : 1; // 25 Dedicated tx fifo for device IN Endpoint - uint32_t num_dev_in_eps : 4; // 26..29 Number of Device IN Endpoints including EP0 - uint32_t dma_desc_enabled : 1; // scatter/gather DMA configuration enabled - uint32_t dma_desc_dynamic : 1; // Dynamic scatter/gather DMA + uint32_t num_dev_period_in_ep : 4; // 0..3 Number of Device Periodic IN Endpoints + uint32_t partial_powerdown : 1; // 4 Partial Power Down Enabled + uint32_t ahb_freq_min : 1; // 5 1: minimum of AHB frequency is less than 60 MHz + uint32_t hibernation : 1; // 6 Hibernation feature is enabled + uint32_t extended_hibernation : 1; // 7 Extended Hibernation feature is enabled + uint32_t reserved8 : 1; // 8 Reserved + uint32_t enhanced_lpm_support1 : 1; // 9 Enhanced LPM Support1 + uint32_t service_interval_flow : 1; // 10 Service Interval flow is supported + uint32_t ipg_isoc_support : 1; // 11 Interpacket GAP ISO OUT worst-case is supported + uint32_t acg_support : 1; // 12 Active clock gating is supported + uint32_t enhanced_lpm_support : 1; // 13 Enhanced LPM Support + uint32_t phy_data_width : 2; // 14..15 0: 8 bits | 1: 16 bits | 2: 8/16 software selectable + uint32_t ctrl_ep_num : 4; // 16..19 Number of Device control endpoints in addition to EP0 + uint32_t iddg_filter : 1; // 20 IDDG Filter Enabled + uint32_t vbus_valid_filter : 1; // 21 VBUS Valid Filter Enabled + uint32_t a_valid_filter : 1; // 22 A Valid Filter Enabled + uint32_t b_valid_filter : 1; // 23 B Valid Filter Enabled + uint32_t session_end_filter : 1; // 24 Session End Filter Enabled + uint32_t dedicated_fifos : 1; // 25 Dedicated tx fifo for device IN Endpoint + uint32_t num_dev_in_eps : 4; // 26..29 Number of Device IN Endpoints including EP0 + uint32_t dma_desc_enabled : 1; // scatter/gather DMA configuration enabled + uint32_t dma_desc_dynamic : 1; // Dynamic scatter/gather DMA }; } dwc2_ghwcfg4_t; TU_VERIFY_STATIC(sizeof(dwc2_ghwcfg4_t) == 4, "incorrect size"); @@ -402,7 +402,7 @@ typedef union { struct TU_ATTR_PACKED { uint32_t fifo_available : 16; // 0..15 Number of words available in the Tx FIFO uint32_t req_queue_available : 8; // 16..23 Number of spaces available in the NPT transmit request queue for both IN and OU - // 24..31 is top entry in the request queue that is currently being processed by the MAC + // 24..31 is top entry in the request queue that is currently being processed by the MAC uint32_t qtop_terminate : 1; // 24 Last entry for selected channel uint32_t qtop_type : 2; // 25..26 Token (0) In/Out (1) ZLP, (2) Ping/cspit, (3) Channel halt command uint32_t qtop_ch_num : 4; // 27..30 Channel number @@ -413,7 +413,7 @@ TU_VERIFY_STATIC(sizeof(dwc2_hnptxsts_t) == 4, "incorrect size"); typedef union { uint32_t value; struct TU_ATTR_PACKED { - uint32_t fifo_available : 16; // 0..15 Number of words available in the Tx FIFO + uint32_t fifo_available :16; // 0..15 Number of words available in the Tx FIFO uint32_t req_queue_available : 7; // 16..22 Number of spaces available in the PTX transmit request queue uint32_t qtop_terminate : 1; // 23 Last entry for selected channel uint32_t qtop_last_period : 1; // 24 Last entry for selected channel is a periodic entry @@ -467,12 +467,12 @@ TU_VERIFY_STATIC(sizeof(dwc2_channel_char_t) == 4, "incorrect size"); typedef union { uint32_t value; struct TU_ATTR_PACKED { - uint32_t hub_port : 7; // 0..6 Hub port number - uint32_t hub_addr : 7; // 7..13 Hub address - uint32_t xact_pos : 2; // 14..15 Transaction position - uint32_t split_compl : 1; // 16 Split completion - uint32_t rsv17_30 : 14; // 17..30 Reserved - uint32_t split_en : 1; // 31 Split enable + uint32_t hub_port : 7; // 0..6 Hub port number + uint32_t hub_addr : 7; // 7..13 Hub address + uint32_t xact_pos : 2; // 14..15 Transaction position + uint32_t split_compl : 1; // 16 Split completion + uint32_t rsv17_30 : 14; // 17..30 Reserved + uint32_t split_en : 1; // 31 Split enable }; } dwc2_channel_split_t; TU_VERIFY_STATIC(sizeof(dwc2_channel_split_t) == 4, "incorrect size"); @@ -480,10 +480,10 @@ TU_VERIFY_STATIC(sizeof(dwc2_channel_split_t) == 4, "incorrect size"); typedef union { uint32_t value; struct TU_ATTR_PACKED { - uint32_t xfer_size : 19; // 0..18 Transfer size in bytes - uint32_t packet_count : 10; // 19..28 Number of packets - uint32_t pid : 2; // 29..30 Packet ID - uint32_t do_ping : 1; // 31 Do PING + uint32_t xfer_size : 19; // 0..18 Transfer size in bytes + uint32_t packet_count : 10; // 19..28 Number of packets + uint32_t pid : 2; // 29..30 Packet ID + uint32_t do_ping : 1; // 31 Do PING }; } dwc2_channel_tsize_t; TU_VERIFY_STATIC(sizeof(dwc2_channel_tsize_t) == 4, "incorrect size"); @@ -499,14 +499,14 @@ TU_VERIFY_STATIC(sizeof(dwc2_hfnum_t) == 4, "incorrect size"); // Host Channel typedef struct { - volatile uint32_t hcchar; // 500 + 20*ch Host Channel Characteristics - volatile uint32_t hcsplt; // 504 + 20*ch Host Channel Split Control - volatile uint32_t hcint; // 508 + 20*ch Host Channel Interrupt - volatile uint32_t hcintmsk; // 50C + 20*ch Host Channel Interrupt Mask - volatile uint32_t hctsiz; // 510 + 20*ch Host Channel Transfer Size - volatile uint32_t hcdma; // 514 + 20*ch Host Channel DMA Address - uint32_t reserved518; // 518 + 20*ch - volatile uint32_t hcdmab; // 51C + 20*ch Host Channel DMA Address + volatile uint32_t hcchar; // 500 + 20*ch Host Channel Characteristics + volatile uint32_t hcsplt; // 504 + 20*ch Host Channel Split Control + volatile uint32_t hcint; // 508 + 20*ch Host Channel Interrupt + volatile uint32_t hcintmsk; // 50C + 20*ch Host Channel Interrupt Mask + volatile uint32_t hctsiz; // 510 + 20*ch Host Channel Transfer Size + volatile uint32_t hcdma; // 514 + 20*ch Host Channel DMA Address + uint32_t reserved518; // 518 + 20*ch + volatile uint32_t hcdmab; // 51C + 20*ch Host Channel DMA Address } dwc2_channel_t; //-------------------------------------------------------------------- @@ -565,7 +565,7 @@ typedef union { uint32_t enum_speed : 2; // 1..2 Enumerated speed uint32_t erratic_err : 1; // 3 Erratic error uint32_t rsv4_7 : 4; // 4..7 Reserved - uint32_t frame_number : 14; // 8..21 Frame/MicroFrame number + uint32_t frame_number :14; // 8..21 Frame/MicroFrame number uint32_t line_status : 2; // 22..23 Line status uint32_t rsv24_31 : 8; // 24..31 Reserved }; @@ -620,23 +620,23 @@ TU_VERIFY_STATIC(sizeof(dwc2_depctl_t) == 4, "incorrect size"); typedef union { uint32_t value; struct TU_ATTR_PACKED { - uint32_t xfer_complete : 1; // 0 Transfer complete - uint32_t disabled : 1; // 1 Endpoint disabled - uint32_t ahb_err : 1; // 2 AHB error - uint32_t setup_phase_done : 1; // 3 Setup phase done - uint32_t out_rx_ep_disabled : 1; // 4 OUT token received when endpoint disabled - uint32_t status_phase_rx : 1; // 5 Status phase received - uint32_t setup_b2b : 1; // 6 Setup packet back-to-back - uint32_t rsv7 : 1; // 7 Reserved - uint32_t out_packet_err : 1; // 8 OUT packet error - uint32_t bna : 1; // 9 Buffer not available - uint32_t rsv10 : 1; // 10 Reserved - uint32_t iso_packet_drop : 1; // 11 Isochronous OUT packet drop status - uint32_t babble_err : 1; // 12 Babble error - uint32_t nak : 1; // 13 NAK - uint32_t nyet : 1; // 14 NYET - uint32_t setup_packet_rx : 1; // 15 Setup packet received (Buffer DMA Mode only) - uint32_t rsv16_31 :16; // 16..31 Reserved + uint32_t xfer_complete : 1; // 0 Transfer complete + uint32_t disabled : 1; // 1 Endpoint disabled + uint32_t ahb_err : 1; // 2 AHB error + uint32_t setup_phase_done : 1; // 3 Setup phase done + uint32_t out_rx_ep_disabled : 1; // 4 OUT token received when endpoint disabled + uint32_t status_phase_rx : 1; // 5 Status phase received + uint32_t setup_b2b : 1; // 6 Setup packet back-to-back + uint32_t rsv7 : 1; // 7 Reserved + uint32_t out_packet_err : 1; // 8 OUT packet error + uint32_t bna : 1; // 9 Buffer not available + uint32_t rsv10 : 1; // 10 Reserved + uint32_t iso_packet_drop : 1; // 11 Isochronous OUT packet drop status + uint32_t babble_err : 1; // 12 Babble error + uint32_t nak : 1; // 13 NAK + uint32_t nyet : 1; // 14 NYET + uint32_t setup_packet_rx : 1; // 15 Setup packet received (Buffer DMA Mode only) + uint32_t rsv16_31 :16; // 16..31 Reserved }; } dwc2_doepint_t; TU_VERIFY_STATIC(sizeof(dwc2_doepint_t) == 4, "incorrect size"); @@ -684,17 +684,17 @@ TU_VERIFY_STATIC(sizeof(dwc2_dep_t) == 0x20, "incorrect size"); // CSR Register Map //-------------------------------------------------------------------- typedef struct { - //------------- Core Global -------------// - volatile uint32_t gotgctl; // 000 OTG Control and Status - volatile uint32_t gotgint; // 004 OTG Interrupt - volatile uint32_t gahbcfg; // 008 AHB Configuration - volatile uint32_t gusbcfg; // 00c USB Configuration - volatile uint32_t grstctl; // 010 Reset - volatile uint32_t gintsts; // 014 Interrupt - volatile uint32_t gintmsk; // 018 Interrupt Mask - volatile uint32_t grxstsr; // 01c Receive Status Debug Read - volatile uint32_t grxstsp; // 020 Receive Status Read/Pop - volatile uint32_t grxfsiz; // 024 Receive FIFO Size + //------------- Core Global ------------- + volatile uint32_t gotgctl; // 000 OTG Control and Status + volatile uint32_t gotgint; // 004 OTG Interrupt + volatile uint32_t gahbcfg; // 008 AHB Configuration + volatile uint32_t gusbcfg; // 00c USB Configuration + volatile uint32_t grstctl; // 010 Reset + volatile uint32_t gintsts; // 014 Interrupt + volatile uint32_t gintmsk; // 018 Interrupt Mask + volatile uint32_t grxstsr; // 01c Receive Status Debug Read + volatile uint32_t grxstsp; // 020 Receive Status Read/Pop + volatile uint32_t grxfsiz; // 024 Receive FIFO Size union { volatile uint32_t dieptxf0; // 028 EP0 Tx FIFO Size volatile uint32_t gnptxfsiz; // 028 Non-periodic Transmit FIFO Size @@ -703,89 +703,89 @@ typedef struct { volatile uint32_t hnptxsts; // 02c Non-periodic Transmit FIFO/Queue Status volatile uint32_t gnptxsts; }; - volatile uint32_t gi2cctl; // 030 I2C Address - volatile uint32_t gpvndctl; // 034 PHY Vendor Control + volatile uint32_t gi2cctl; // 030 I2C Address + volatile uint32_t gpvndctl; // 034 PHY Vendor Control union { volatile uint32_t ggpio; // 038 General Purpose IO volatile uint32_t stm32_gccfg; // 038 STM32 General Core Configuration }; - volatile uint32_t guid; // 03C User (Application programmable) ID - volatile uint32_t gsnpsid; // 040 Synopsys ID + Release version - volatile uint32_t ghwcfg1; // 044 User Hardware Configuration1: endpoint dir (2 bit per ep) - volatile uint32_t ghwcfg2; // 048 User Hardware Configuration2 - volatile uint32_t ghwcfg3; // 04C User Hardware Configuration3 + volatile uint32_t guid; // 03C User (Application programmable) ID + volatile uint32_t gsnpsid; // 040 Synopsys ID + Release version + volatile uint32_t ghwcfg1; // 044 User Hardware Configuration1: endpoint dir (2 bit per ep) + volatile uint32_t ghwcfg2; // 048 User Hardware Configuration2 + volatile uint32_t ghwcfg3; // 04C User Hardware Configuration3 union { volatile uint32_t ghwcfg4; // 050 User Hardware Configuration4 volatile dwc2_ghwcfg4_t ghwcfg4_bm; }; - volatile uint32_t glpmcfg; // 054 Core LPM Configuration - volatile uint32_t gpwrdn; // 058 Power Down - volatile uint32_t gdfifocfg; // 05C DFIFO Software Configuration - volatile uint32_t gadpctl; // 060 ADP Timer, Control and Status - uint32_t reserved64[39]; // 064..0FF - volatile uint32_t hptxfsiz; // 100 Host Periodic Tx FIFO Size - volatile uint32_t dieptxf[15]; // 104..13C Device Periodic Transmit FIFO Size - uint32_t reserved140[176]; // 140..3FF + volatile uint32_t glpmcfg; // 054 Core LPM Configuration + volatile uint32_t gpwrdn; // 058 Power Down + volatile uint32_t gdfifocfg; // 05C DFIFO Software Configuration + volatile uint32_t gadpctl; // 060 ADP Timer, Control and Status + uint32_t reserved64[39]; // 064..0FF + volatile uint32_t hptxfsiz; // 100 Host Periodic Tx FIFO Size + volatile uint32_t dieptxf[15]; // 104..13C Device Periodic Transmit FIFO Size + uint32_t reserved140[176]; // 140..3FF - //------------ Host -------------// - volatile uint32_t hcfg; // 400 Host Configuration - volatile uint32_t hfir; // 404 Host Frame Interval - volatile uint32_t hfnum; // 408 Host Frame Number / Frame Remaining - uint32_t reserved40c; // 40C - volatile uint32_t hptxsts; // 410 Host Periodic TX FIFO / Queue Status - volatile uint32_t haint; // 414 Host All Channels Interrupt - volatile uint32_t haintmsk; // 418 Host All Channels Interrupt Mask - volatile uint32_t hflbaddr; // 41C Host Frame List Base Address - uint32_t reserved420[8]; // 420..43F - volatile uint32_t hprt; // 440 Host Port Control and Status - uint32_t reserved444[47]; // 444..4FF + //------------ Host ------------- + volatile uint32_t hcfg; // 400 Host Configuration + volatile uint32_t hfir; // 404 Host Frame Interval + volatile uint32_t hfnum; // 408 Host Frame Number / Frame Remaining + uint32_t reserved40c; // 40C + volatile uint32_t hptxsts; // 410 Host Periodic TX FIFO / Queue Status + volatile uint32_t haint; // 414 Host All Channels Interrupt + volatile uint32_t haintmsk; // 418 Host All Channels Interrupt Mask + volatile uint32_t hflbaddr; // 41C Host Frame List Base Address + uint32_t reserved420[8]; // 420..43F + volatile uint32_t hprt; // 440 Host Port Control and Status + uint32_t reserved444[47]; // 444..4FF - //------------- Host Channel -------------// - dwc2_channel_t channel[16]; // 500..6FF Host Channels 0-15 - uint32_t reserved700[64]; // 700..7FF + //------------- Host Channel -------- + dwc2_channel_t channel[16]; // 500..6FF Host Channels 0-15 + uint32_t reserved700[64]; // 700..7FF - //------------- Device -----------// - volatile uint32_t dcfg; // 800 Device Configuration - volatile uint32_t dctl; // 804 Device Control - volatile uint32_t dsts; // 808 Device Status (RO) - uint32_t reserved80c; // 80C - volatile uint32_t diepmsk; // 810 Device IN Endpoint Interrupt Mask - volatile uint32_t doepmsk; // 814 Device OUT Endpoint Interrupt Mask - volatile uint32_t daint; // 818 Device All Endpoints Interrupt - volatile uint32_t daintmsk; // 81C Device All Endpoints Interrupt Mask - volatile uint32_t dtknqr1; // 820 Device IN token sequence learning queue read1 - volatile uint32_t dtknqr2; // 824 Device IN token sequence learning queue read2 - volatile uint32_t dvbusdis; // 828 Device VBUS Discharge Time - volatile uint32_t dvbuspulse; // 82C Device VBUS Pulsing Time - volatile uint32_t dthrctl; // 830 Device threshold Control - volatile uint32_t diepempmsk; // 834 Device IN Endpoint FIFO Empty Interrupt Mask + //------------- Device ----------- + volatile uint32_t dcfg; // 800 Device Configuration + volatile uint32_t dctl; // 804 Device Control + volatile uint32_t dsts; // 808 Device Status (RO) + uint32_t reserved80c; // 80C + volatile uint32_t diepmsk; // 810 Device IN Endpoint Interrupt Mask + volatile uint32_t doepmsk; // 814 Device OUT Endpoint Interrupt Mask + volatile uint32_t daint; // 818 Device All Endpoints Interrupt + volatile uint32_t daintmsk; // 81C Device All Endpoints Interrupt Mask + volatile uint32_t dtknqr1; // 820 Device IN token sequence learning queue read1 + volatile uint32_t dtknqr2; // 824 Device IN token sequence learning queue read2 + volatile uint32_t dvbusdis; // 828 Device VBUS Discharge Time + volatile uint32_t dvbuspulse; // 82C Device VBUS Pulsing Time + volatile uint32_t dthrctl; // 830 Device threshold Control + volatile uint32_t diepempmsk; // 834 Device IN Endpoint FIFO Empty Interrupt Mask - // Device Each Endpoint (IN/OUT) Interrupt/Mask for generating dedicated EP interrupt line - // require OTG_MULTI_PROC_INTRPT=1 - volatile uint32_t deachint; // 838 Device Each Endpoint Interrupt - volatile uint32_t deachmsk; // 83C Device Each Endpoint Interrupt mask - volatile uint32_t diepeachmsk[16]; // 840..87C Device Each IN Endpoint mask - volatile uint32_t doepeachmsk[16]; // 880..8BF Device Each OUT Endpoint mask - uint32_t reserved8c0[16]; // 8C0..8FF + // Device Each Endpoint (IN/OUT) Interrupt/Mask for generating dedicated EP interrupt line require + // OTG_MULTI_PROC_INTRPT=1 + volatile uint32_t deachint; // 838 Device Each Endpoint Interrupt + volatile uint32_t deachmsk; // 83C Device Each Endpoint Interrupt mask + volatile uint32_t diepeachmsk[16]; // 840..87C Device Each IN Endpoint mask + volatile uint32_t doepeachmsk[16]; // 880..8BF Device Each OUT Endpoint mask + uint32_t reserved8c0[16]; // 8C0..8FF - //------------- Device Endpoint -------------// + //------------- Device Endpoint ----- union { - dwc2_dep_t ep[2][16]; // 0: IN, 1 OUT + dwc2_dep_t ep[2][16]; // 0: IN, 1 OUT struct { - dwc2_dep_t epin[16]; // 900..AFF IN Endpoints - dwc2_dep_t epout[16]; // B00..CFF OUT Endpoints + dwc2_dep_t epin[16]; // 900..AFF IN Endpoints + dwc2_dep_t epout[16]; // B00..CFF OUT Endpoints }; }; - uint32_t reservedd00[64]; // D00..DFF + uint32_t reservedd00[64]; // D00..DFF - //------------- Power Clock -------------// - volatile uint32_t pcgcctl; // E00 Power and Clock Gating Characteristic Control - volatile uint32_t pcgcctl1; // E04 Power and Clock Gating Characteristic Control 1 - uint32_t reservede08[126]; // E08..FFF + //------------- Power Clock --------- + volatile uint32_t pcgcctl; // E00 Power and Clock Gating Characteristic Control + volatile uint32_t pcgcctl1; // E04 Power and Clock Gating Characteristic Control 1 + uint32_t reservede08[126]; // E08..FFF - //------------- FIFOs -------------// + //------------- FIFOs ------------- // Word-accessed only using first pointer since it auto shift - volatile uint32_t fifo[16][0x400]; // 1000..FFFF Endpoint FIFO + volatile uint32_t fifo[16][0x400]; // 1000..FFFF Endpoint FIFO } dwc2_regs_t; TU_VERIFY_STATIC(offsetof(dwc2_regs_t, hcfg ) == 0x0400, "incorrect size"); diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 8f1103415..8d565d174 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -44,8 +44,6 @@ #endif #define DWC2_CHANNEL_COUNT_MAX 16 // absolute max channel count -#define DWC2_CHANNEL_COUNT(_dwc2) ({const dwc2_ghwcfg2_t ghwcfg2 = {.value = (_dwc2)->ghwcfg2}; tu_min8(ghwcfg2.num_host_ch + 1, DWC2_CHANNEL_COUNT_MAX);}) - TU_VERIFY_STATIC(CFG_TUH_DWC2_ENDPOINT_MAX <= 255, "currently only use 8-bit for index"); enum { @@ -116,6 +114,11 @@ hcd_data_t _hcd_data; //-------------------------------------------------------------------- // //-------------------------------------------------------------------- +TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_channel_count(const dwc2_regs_t* dwc2) { + const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; + return tu_min8(ghwcfg2.num_host_ch + 1, DWC2_CHANNEL_COUNT_MAX); +} + TU_ATTR_ALWAYS_INLINE static inline tusb_speed_t hprt_speed_get(dwc2_regs_t* dwc2) { tusb_speed_t speed; const dwc2_hprt_t hprt = {.value = dwc2->hprt}; @@ -157,7 +160,7 @@ bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) { // Allocate a channel for new transfer TU_ATTR_ALWAYS_INLINE static inline uint8_t channel_alloc(dwc2_regs_t* dwc2) { - const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2); + const uint8_t max_channel = dwc2_channel_count(dwc2); for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) { hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; if (!xfer->allocated) { @@ -208,7 +211,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool channel_send_in_token(const dwc2_regs_t // Find currently enabled channel. Note: EP0 is bidirectional TU_ATTR_ALWAYS_INLINE static inline uint8_t channel_find_enabled(dwc2_regs_t* dwc2, uint8_t dev_addr, uint8_t ep_num, uint8_t ep_dir) { - const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2); + const uint8_t max_channel = dwc2_channel_count(dwc2); for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) { if (_hcd_data.xfer[ch_id].allocated) { const dwc2_channel_char_t hcchar = {.value = dwc2->channel[ch_id].hcchar}; @@ -813,7 +816,7 @@ static bool handle_txfifo_empty(dwc2_regs_t* dwc2, bool is_periodic) { // Use period txsts for both p/np to get request queue space available (1-bit difference, it is small enough) const dwc2_hptxsts_t txsts = {.value = (is_periodic ? dwc2->hptxsts : dwc2->hnptxsts)}; - const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2); + const uint8_t max_channel = dwc2_channel_count(dwc2); for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) { dwc2_channel_t* channel = &dwc2->channel[ch_id]; const dwc2_channel_char_t hcchar = {.value = channel->hcchar}; @@ -1168,7 +1171,7 @@ static bool handle_channel_out_dma(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hc static void handle_channel_irq(uint8_t rhport, bool in_isr) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); const bool is_dma = dma_host_enabled(dwc2); - const uint8_t max_channel = DWC2_CHANNEL_COUNT(dwc2); + const uint8_t max_channel = dwc2_channel_count(dwc2); for (uint8_t ch_id = 0; ch_id < max_channel; ch_id++) { if (tu_bit_test(dwc2->haint, ch_id)) { From 384e191fdc9346eb8718f1f3e50f4697f161cc88 Mon Sep 17 00:00:00 2001 From: Maxime Vincent Date: Thu, 10 Apr 2025 10:29:45 +0200 Subject: [PATCH 114/382] dwc2/host: immediately retry IN token for bInterval=1 Signed-off-by: Maxime Vincent --- src/portable/synopsys/dwc2/hcd_dwc2.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 33c0edba1..6e2737afd 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -736,6 +736,14 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci } } + // immediately retry if bInterval is 1 - otherwise we'd waste a microframe before retrying + if ((hcint & HCINT_HALTED) && (edpt->uframe_interval == 1)) { + edpt->hcchar_bm.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame + channel->hcchar = (edpt->hcchar & ~HCCHAR_CHENA); + channel_send_in_token(dwc2, channel); + return; + } + // for periodic, de-allocate channel, enable SOF set frame counter for later transfer const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; edpt->next_pid = hctsiz.pid; // save PID From 62d06e7b19d82dbbc3d1089b249913c13eb7fc2a Mon Sep 17 00:00:00 2001 From: Maxime Vincent Date: Mon, 14 Apr 2025 09:24:54 +0200 Subject: [PATCH 115/382] dwc2/host: fix all retry intervals Signed-off-by: Maxime Vincent --- src/portable/synopsys/dwc2/hcd_dwc2.c | 31 +++++++++++++-------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 6e2737afd..d2070e57c 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -736,23 +736,22 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci } } - // immediately retry if bInterval is 1 - otherwise we'd waste a microframe before retrying - if ((hcint & HCINT_HALTED) && (edpt->uframe_interval == 1)) { - edpt->hcchar_bm.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame - channel->hcchar = (edpt->hcchar & ~HCCHAR_CHENA); - channel_send_in_token(dwc2, channel); - return; - } - - // for periodic, de-allocate channel, enable SOF set frame counter for later transfer - const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; - edpt->next_pid = hctsiz.pid; // save PID - edpt->uframe_countdown = edpt->uframe_interval; - dwc2->gintmsk |= GINTSTS_SOF; - if (hcint & HCINT_HALTED) { - // already halted, de-allocate channel (called from DMA isr) - channel_dealloc(dwc2, ch_id); + const uint32_t ucount = (hprt_speed_get(dwc2) == TUSB_SPEED_HIGH ? 1 : 8); + if (edpt->uframe_interval == ucount) { + // immediately retry if bInterval is 1 + edpt->hcchar_bm.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame + channel->hcchar = (edpt->hcchar & ~HCCHAR_CHENA); + channel_send_in_token(dwc2, channel); + } else { + // otherwise, de-allocate channel, enable SOF set frame counter for later transfer + const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; + edpt->next_pid = hctsiz.pid; // save PID + edpt->uframe_countdown = edpt->uframe_interval - ucount; + dwc2->gintmsk |= GINTSTS_SOF; + // already halted, de-allocate channel (called from DMA isr) + channel_dealloc(dwc2, ch_id); + } } else { // disable channel first if not halted (called slave isr) xfer->halted_sof_schedule = 1; From 0d2c08efd7145b160ab0ed373b2cf956699cfb74 Mon Sep 17 00:00:00 2001 From: Joel Michael Date: Wed, 16 Apr 2025 20:26:35 +1000 Subject: [PATCH 116/382] note potential issues using ep_desc in hcd_edpt_open() --- src/portable/template/hcd_template.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/portable/template/hcd_template.c b/src/portable/template/hcd_template.c index b073d6057..694fa8550 100644 --- a/src/portable/template/hcd_template.c +++ b/src/portable/template/hcd_template.c @@ -116,6 +116,10 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { (void) rhport; (void) dev_addr; + + // NOTE: ep_desc is allocated on the stack when called from usbh_edpt_control_open() + // If you need to persist any ep_desc values across HCD calls (eg ep_desc->wMaxPacketSize), + // then you need to copy the data into another variable inside this function. (void) ep_desc; return false; From 4d601545eba2793280752fb04ab6a7628a1a14ea Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 16 Apr 2025 21:15:07 +0700 Subject: [PATCH 117/382] add TS3USB30 to test s3 host with slave/dma --- hw/bsp/espressif/boards/espressif_p4_function_ev/board.h | 7 ++++--- hw/bsp/espressif/boards/espressif_s3_devkitm/board.h | 5 +++++ hw/bsp/espressif/boards/family.c | 8 ++++---- test/hil/tinyusb.json | 8 +++++--- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h b/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h index 6f3229b70..40c4963d9 100644 --- a/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h +++ b/hw/bsp/espressif/boards/espressif_p4_function_ev/board.h @@ -41,9 +41,10 @@ #define BUTTON_PIN 35 #define BUTTON_STATE_ACTIVE 0 -// For CI hardware test, to test both device and host on the same HS port with help of -#define HIL_DEVICE_HOST_MUX_PIN 47 -#define HIL_DEVICE_STATE 1 +// For CI hardware test, to test both device and host on the same HS port with help of TS3USB30 +// https://www.adafruit.com/product/5871 +#define HIL_TS3USB30_MODE_PIN 47 +#define HIL_TS3USB30_MODE_DEVICE 1 #ifdef __cplusplus } diff --git a/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h b/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h index d01fdbe5b..5c1914ebe 100644 --- a/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h +++ b/hw/bsp/espressif/boards/espressif_s3_devkitm/board.h @@ -49,6 +49,11 @@ #define MAX3421_CS_PIN 15 #define MAX3421_INTR_PIN 14 +// For CI hardware test, to test both device and host on the same HS port with help of TS3USB30 +// https://www.adafruit.com/product/5871 +#define HIL_TS3USB30_MODE_PIN 47 +#define HIL_TS3USB30_MODE_DEVICE 1 + #ifdef __cplusplus } #endif diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index 7049c0415..cf11e2441 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -92,10 +92,10 @@ void board_init(void) { usb_init(); #endif -#ifdef HIL_DEVICE_HOST_MUX_PIN - gpio_reset_pin(HIL_DEVICE_HOST_MUX_PIN); - gpio_set_direction(HIL_DEVICE_HOST_MUX_PIN, GPIO_MODE_OUTPUT); - gpio_set_level(HIL_DEVICE_HOST_MUX_PIN, CFG_TUD_ENABLED ? HIL_DEVICE_STATE : (1-HIL_DEVICE_STATE)); +#ifdef HIL_TS3USB30_MODE_PIN + gpio_reset_pin(HIL_TS3USB30_MODE_PIN); + gpio_set_direction(HIL_TS3USB30_MODE_PIN, GPIO_MODE_OUTPUT); + gpio_set_level(HIL_TS3USB30_MODE_PIN, CFG_TUD_ENABLED ? HIL_TS3USB30_MODE_DEVICE : (1-HIL_TS3USB30_MODE_DEVICE)); #endif #if CFG_TUH_ENABLED && CFG_TUH_MAX3421 diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index a9460bf9d..8f39eb32e 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -21,16 +21,18 @@ "name": "espressif_s3_devkitm", "uid": "84F703C084E4", "build" : { - "flags_on": ["", "CFG_TUD_DWC2_DMA_ENABLE"] + "flags_on": ["", "CFG_TUD_DWC2_DMA_ENABLE CFG_TUH_DWC2_DMA_ENABLE"] }, "tests": { - "only": ["device/cdc_msc_freertos", "device/hid_composite_freertos"] + "only": ["device/cdc_msc_freertos", "device/hid_composite_freertos", "host/device_info"], + "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2005402"}] }, "flasher": { "name": "esptool", "uid": "3ea619acd1cdeb11a0a0b806e93fd3f1", "args": "-b 1500000" - } + }, + "comment": "Use TS3USB30 mux to test both device and host" }, { "name": "feather_nrf52840_express", From 7ef17a85cb5c6655e778e3385dfef20be00de199 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 16 Apr 2025 22:04:19 +0700 Subject: [PATCH 118/382] de-duplicate flash board_test for board with multiple flags_on --- test/hil/hil_test.py | 103 +++++++++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 43 deletions(-) diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 8b89de66c..14ab4e63a 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -514,6 +514,63 @@ host_test = [ ] +def test_example(board, f1, example): + """ + Test example firmware + :param board: board dict + :param f1: flags on + :param example: example name + :return: 0 if success/skip, 1 if failed + """ + name = board['name'] + err_count = 0 + + f1_str = "" + if f1 != "": + f1_str = '-f1_' + f1.replace(' ', '_') + + fw_dir = f'{TINYUSB_ROOT}/cmake-build/cmake-build-{name}{f1_str}/{example}' + if not os.path.exists(fw_dir): + fw_dir = f'{TINYUSB_ROOT}/examples/cmake-build-{name}{f1_str}/{example}' + fw_name = f'{fw_dir}/{os.path.basename(example)}' + print(f'{name+f1_str:40} {example:30} ... ', end='') + + if not os.path.exists(fw_dir) or not (os.path.exists(f'{fw_name}.elf') or os.path.exists(f'{fw_name}.bin')): + print('Skip (no binary)') + return 0 + + if verbose: + print(f'Flashing {fw_name}.elf') + + # flash firmware. It may fail randomly, retry a few times + max_rety = 2 + for i in range(max_rety): + ret = globals()[f'flash_{board["flasher"]["name"].lower()}'](board, fw_name) + if ret.returncode == 0: + try: + globals()[f'test_{example.replace("/", "_")}'](board) + print('OK') + break + except Exception as e: + if i == max_rety - 1: + err_count += 1 + print(STATUS_FAILED) + print(f' {e}') + else: + print() + print(f' Test failed: {e}, retry {i+2}/{max_rety}') + time.sleep(1) + else: + print(f'Flashing failed, retry {i+2}/{max_rety}') + time.sleep(1) + + if ret.returncode != 0: + err_count += 1 + print(f'Flash {STATUS_FAILED}') + + return err_count + + def test_board(board): name = board['name'] flasher = board['flasher'] @@ -537,57 +594,17 @@ def test_board(board): test_list.remove(skip) print(f'{name:25} {skip:30} ... Skip') - # board_test is added last to disable board's usb - test_list.append('device/board_test') - err_count = 0 flags_on_list = [""] if 'build' in board and 'flags_on' in board['build']: flags_on_list = board['build']['flags_on'] for f1 in flags_on_list: - f1_str = "" - if f1 != "": - f1_str = '-f1_' + f1.replace(' ', '_') for test in test_list: - fw_dir = f'{TINYUSB_ROOT}/cmake-build/cmake-build-{name}{f1_str}/{test}' - if not os.path.exists(fw_dir): - fw_dir = f'{TINYUSB_ROOT}/examples/cmake-build-{name}{f1_str}/{test}' - fw_name = f'{fw_dir}/{os.path.basename(test)}' - print(f'{name+f1_str:40} {test:30} ... ', end='') + err_count += test_example(board, f1, test) - if not os.path.exists(fw_dir) or not (os.path.exists(f'{fw_name}.elf') or os.path.exists(f'{fw_name}.bin')): - print('Skip (no binary)') - continue - - if verbose: - print(f'Flashing {fw_name}.elf') - - # flash firmware. It may fail randomly, retry a few times - max_rety = 2 - for i in range(max_rety): - ret = globals()[f'flash_{flasher["name"].lower()}'](board, fw_name) - if ret.returncode == 0: - try: - globals()[f'test_{test.replace("/", "_")}'](board) - print('OK') - break - except Exception as e: - if i == max_rety - 1: - err_count += 1 - print(STATUS_FAILED) - print(f' {e}') - else: - print() - print(f' Test failed: {e}, retry {i+2}/{max_rety}') - time.sleep(1) - else: - print(f'Flashing failed, retry {i+2}/{max_rety}') - time.sleep(1) - - if ret.returncode != 0: - err_count += 1 - print(f'Flash {STATUS_FAILED}') + # flash board_test last to disable board's usb + test_example(board, flags_on_list[0], 'device/board_test') return err_count From f479b02ea6110d2b7703ae96763535b7ec2bbde1 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Apr 2025 11:22:38 +0700 Subject: [PATCH 119/382] ci add pico_w for native host test --- .../boards/raspberry_pi_pico_w/board.cmake | 2 + .../rp2040/boards/raspberry_pi_pico_w/board.h | 70 +++++++++++++++++++ test/hil/tinyusb.json | 14 ++++ 3 files changed, 86 insertions(+) create mode 100644 hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.cmake create mode 100644 hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.h diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.cmake b/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.cmake new file mode 100644 index 000000000..97621d855 --- /dev/null +++ b/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.cmake @@ -0,0 +1,2 @@ +set(PICO_PLATFORM rp2040) +set(PICO_BOARD pico_w) diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.h b/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.h new file mode 100644 index 000000000..8af32fc9e --- /dev/null +++ b/hw/bsp/rp2040/boards/raspberry_pi_pico_w/board.h @@ -0,0 +1,70 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: Pico + url: https://www.raspberrypi.com/products/raspberry-pi-pico/ +*/ + +#ifndef TUSB_BOARD_H +#define TUSB_BOARD_H + +#ifdef __cplusplus + extern "C" { +#endif + +// UART and LED are already defined in pico-sdk board + +//--------------------------------------------------------------------+ +// PIO_USB +//--------------------------------------------------------------------+ +// default to pico brain tester +#define PICO_DEFAULT_PIO_USB_DP_PIN 20 +#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 22 +#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1 + +//-------------------------------------------------------------------- +// USB Host MAX3421E +//-------------------------------------------------------------------- + +#ifdef PICO_DEFAULT_SPI +#define MAX3421_SPI PICO_DEFAULT_SPI // sdk v2 +#else +#define MAX3421_SPI PICO_DEFAULT_SPI_INSTANCE // sdk v1 +#endif + +#define MAX3421_SCK_PIN PICO_DEFAULT_SPI_SCK_PIN +#define MAX3421_MOSI_PIN PICO_DEFAULT_SPI_TX_PIN +#define MAX3421_MISO_PIN PICO_DEFAULT_SPI_RX_PIN +#define MAX3421_CS_PIN 10 +#define MAX3421_INTR_PIN 9 + + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index 8f39eb32e..8a835e4c0 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -126,6 +126,20 @@ "args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\"" } }, + { + "name": "raspberry_pi_pico_w", + "uid": "E6614C311B764A37", + "tests": { + "device": false, "host": true, "dual": false, + "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2023934"}] + }, + "flasher": { + "name": "openocd", + "uid": "E6633861A3819D38", + "args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\"" + }, + "comment": "Test native host" + }, { "name": "raspberry_pi_pico2", "uid": "560AE75E1C7152C9", From ccb34dbbdb24638ab030e1966b956330c15a1b88 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Apr 2025 11:58:05 +0700 Subject: [PATCH 120/382] add toolchain.json for toolchain url --- .circleci/config2.yml | 12 +----------- .github/actions/setup_toolchain/action.yml | 9 +-------- .github/actions/setup_toolchain/toolchain.json | 9 +++++++++ 3 files changed, 11 insertions(+), 19 deletions(-) create mode 100644 .github/actions/setup_toolchain/toolchain.json diff --git a/.circleci/config2.yml b/.circleci/config2.yml index 3b0294168..c1f080556 100644 --- a/.circleci/config2.yml +++ b/.circleci/config2.yml @@ -10,17 +10,7 @@ commands: - run: name: Set toolchain url and key command: | - TOOLCHAIN_JSON='{ - "aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz", - "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz", - "arm-gcc": "https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v13.2.1-1.1/xpack-arm-none-eabi-gcc-13.2.1-1.1-linux-x64.tar.gz", - "msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2", - "riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz", - "rx-gcc": "https://github.com/hathach/rx_device/releases/download/0.0.1/gcc-8.3.0.202411-GNURX-ELF.run", - "arm-iar": "https://updates.iar.com/FileStore/STANDARD/001/003/322/cxarm-9.60.3.deb" - }' - toolchain_url=$(echo $TOOLCHAIN_JSON | jq -r '.["<< parameters.toolchain >>"]') - + toolchain_url=$(jq -r '."<< parameters.toolchain >>"' .github/actions/setup_toolchain/toolchain.json) # only cache if not a github link if [[ $toolchain_url != "https://github.com"* ]]; then echo "<< parameters.toolchain >>-$toolchain_url" > toolchain_key diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml index 8305daa24..7c1f92c1a 100644 --- a/.github/actions/setup_toolchain/action.yml +++ b/.github/actions/setup_toolchain/action.yml @@ -32,14 +32,7 @@ runs: inputs.toolchain != 'esp-idf' id: set-toolchain-url run: | - TOOLCHAIN_JSON='{ - "aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz", - "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz", - "msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2", - "riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz", - "rx-gcc": "https://github.com/hathach/rx_device/releases/download/0.0.1/gcc-8.3.0.202411-GNURX-ELF.run" - }' - TOOLCHAIN_URL=$(echo $TOOLCHAIN_JSON | jq -r '.["${{ inputs.toolchain }}"]') + TOOLCHAIN_URL=$(jq -r '."${{ inputs.toolchain }}"' .github/actions/setup_toolchain/toolchain.json) echo "toolchain_url=$TOOLCHAIN_URL" echo "toolchain_url=$TOOLCHAIN_URL" >> $GITHUB_OUTPUT shell: bash diff --git a/.github/actions/setup_toolchain/toolchain.json b/.github/actions/setup_toolchain/toolchain.json new file mode 100644 index 000000000..4e65f1cbe --- /dev/null +++ b/.github/actions/setup_toolchain/toolchain.json @@ -0,0 +1,9 @@ +{ + "aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz", + "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz", + "arm-gcc": "https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v13.2.1-1.1/xpack-arm-none-eabi-gcc-13.2.1-1.1-linux-x64.tar.gz", + "msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2", + "riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz", + "rx-gcc": "https://github.com/hathach/rx_device/releases/download/0.0.1/gcc-8.3.0.202411-GNURX-ELF.run", + "arm-iar": "https://netstorage.iar.com/FileStore/STANDARD/001/003/583/cxarm-9.60.4.deb" +} From eea42fd1197bea01eb480363ccf573544f4c9551 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Apr 2025 13:05:18 +0700 Subject: [PATCH 121/382] update iar build --- .circleci/config.yml | 4 ++-- .circleci/config2.yml | 1 - .github/workflows/build.yml | 2 -- .github/workflows/hil_test.yml | 2 -- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fd5631e2e..a7ae6980f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -20,17 +20,17 @@ jobs: BUILDSYSTEM_TOOLCHAIN=( "cmake arm-clang" + "cmake esp-idf" "make aarch64-gcc" "make arm-gcc" "make msp430-gcc" "make riscv-gcc" "make rx-gcc" - "cmake esp-idf" ) # only build IAR if not forked PR, since IAR token is not shared if [ -z $CIRCLE_PR_USERNAME ]; then - BUILDSYSTEM_TOOLCHAIN+=("cmake arm-iar") + BUILDSYSTEM_TOOLCHAIN+=("make arm-iar") fi RESOURCE_LARGE='["nrf", "imxrt", "stm32f4", "stm32h7"]' diff --git a/.circleci/config2.yml b/.circleci/config2.yml index c1f080556..d86a3f662 100644 --- a/.circleci/config2.yml +++ b/.circleci/config2.yml @@ -111,7 +111,6 @@ commands: TOOLCHAIN_OPTION="--toolchain clang" elif [ << parameters.toolchain >> == arm-iar ]; then TOOLCHAIN_OPTION="--toolchain iar" - echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL iccarm --version elif [ << parameters.toolchain >> == arm-gcc ]; then TOOLCHAIN_OPTION="--toolchain gcc" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 547763bd8..f42499ef7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -119,7 +119,6 @@ jobs: runs-on: [self-hosted, Linux, X64, hifiphile] env: BUILD_ARGS: ${{ join(fromJSON(needs.set-matrix.outputs.json)['arm-iar'], ' ') }} - IAR_LMS_CLOUD_URL: ${{ vars.IAR_LMS_CLOUD_URL }} IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} steps: - name: Clean workspace @@ -130,7 +129,6 @@ jobs: - name: Toolchain version run: | - echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL iccarm --version - name: Checkout TinyUSB diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml index c890933ec..257416213 100644 --- a/.github/workflows/hil_test.yml +++ b/.github/workflows/hil_test.yml @@ -96,7 +96,6 @@ jobs: if: github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false runs-on: [self-hosted, Linux, X64, hifiphile] env: - IAR_LMS_CLOUD_URL: ${{ vars.IAR_LMS_CLOUD_URL }} IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} steps: - name: Clean workspace @@ -107,7 +106,6 @@ jobs: - name: Toolchain version run: | - echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL iccarm --version - name: Checkout TinyUSB From b1eedf4d1d95d6e8c7de425080a107a33cbf0e5d Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Apr 2025 14:34:55 +0700 Subject: [PATCH 122/382] fix iar make build with wb and u5 --- examples/build_system/make/cpu/cortex-m4.mk | 4 ++-- examples/host/msc_file_explorer/Makefile | 2 +- hw/bsp/broadcom_32bit/family.mk | 2 +- hw/bsp/broadcom_64bit/family.mk | 2 +- .../boards/frdm_k32l2a4s/board.mk | 2 +- hw/bsp/lpc15/family.mk | 2 +- hw/bsp/lpc17/family.mk | 2 +- hw/bsp/lpc18/family.mk | 2 +- hw/bsp/lpc40/family.mk | 2 +- hw/bsp/lpc43/family.mk | 6 +++--- hw/bsp/stm32f4/family.mk | 1 - hw/bsp/stm32u5/boards/b_u585i_iot2a/board.mk | 4 +--- .../stm32u5/boards/stm32u545nucleo/board.mk | 4 +--- hw/bsp/stm32u5/boards/stm32u575eval/board.mk | 4 +--- .../stm32u5/boards/stm32u575nucleo/board.mk | 4 +--- .../stm32u5/boards/stm32u5a5nucleo/board.mk | 4 +--- hw/bsp/stm32u5/family.mk | 7 +++++++ hw/bsp/stm32wb/family.mk | 21 ++++++++++++------- src/class/msc/msc_device.c | 5 +++-- 19 files changed, 41 insertions(+), 39 deletions(-) diff --git a/examples/build_system/make/cpu/cortex-m4.mk b/examples/build_system/make/cpu/cortex-m4.mk index 4e16819d1..57d6e126d 100644 --- a/examples/build_system/make/cpu/cortex-m4.mk +++ b/examples/build_system/make/cpu/cortex-m4.mk @@ -12,8 +12,8 @@ else ifeq ($(TOOLCHAIN),clang) -mfpu=fpv4-sp-d16 \ else ifeq ($(TOOLCHAIN),iar) - CFLAGS += --cpu cortex-m4 --fpu VFPv4 - ASFLAGS += --cpu cortex-m4 --fpu VFPv4 + CFLAGS += --cpu cortex-m4 --fpu VFPv4-SP + ASFLAGS += --cpu cortex-m4 --fpu VFPv4-SP else $(error "TOOLCHAIN is not supported") diff --git a/examples/host/msc_file_explorer/Makefile b/examples/host/msc_file_explorer/Makefile index c7d6a7cae..f0872376f 100644 --- a/examples/host/msc_file_explorer/Makefile +++ b/examples/host/msc_file_explorer/Makefile @@ -22,6 +22,6 @@ SRC_C += \ $(FATFS_PATH)/ffunicode.c \ # suppress warning caused by fatfs -CFLAGS += -Wno-error=cast-qual +CFLAGS_GCC += -Wno-error=cast-qual include ../../build_system/make/rules.mk diff --git a/hw/bsp/broadcom_32bit/family.mk b/hw/bsp/broadcom_32bit/family.mk index a282e9961..9d4a3b76c 100644 --- a/hw/bsp/broadcom_32bit/family.mk +++ b/hw/bsp/broadcom_32bit/family.mk @@ -15,7 +15,7 @@ CFLAGS += \ CROSS_COMPILE = arm-none-eabi- # mcu driver cause following warnings -CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls +CFLAGS_GCC += -Wno-error=cast-qual -Wno-error=redundant-decls SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ diff --git a/hw/bsp/broadcom_64bit/family.mk b/hw/bsp/broadcom_64bit/family.mk index 37d381f9f..1ce80e22b 100644 --- a/hw/bsp/broadcom_64bit/family.mk +++ b/hw/bsp/broadcom_64bit/family.mk @@ -14,7 +14,7 @@ CFLAGS += \ CROSS_COMPILE = aarch64-none-elf- # mcu driver cause following warnings -CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls +CFLAGS_GCC += -Wno-error=cast-qual -Wno-error=redundant-decls SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ diff --git a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk index c4dc65b63..fb3eb2a03 100644 --- a/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk +++ b/hw/bsp/kinetis_k32l2/boards/frdm_k32l2a4s/board.mk @@ -3,7 +3,7 @@ MCU = K32L2A41A CFLAGS += -DCPU_K32L2A41VLH1A # mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter -Wno-error=redundant-decls -Wno-error=cast-qual +CFLAGS_GCC += -Wno-error=unused-parameter -Wno-error=redundant-decls -Wno-error=cast-qual # All source paths should be relative to the top level. LD_FILE = $(MCU_DIR)/gcc/K32L2A41xxxxA_flash.ld diff --git a/hw/bsp/lpc15/family.mk b/hw/bsp/lpc15/family.mk index b83e008e8..3b63580c0 100644 --- a/hw/bsp/lpc15/family.mk +++ b/hw/bsp/lpc15/family.mk @@ -15,7 +15,7 @@ CFLAGS += \ LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs # mcu driver cause following warnings -CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=unused-variable -Wno-error=cast-qual +CFLAGS_GCC += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=unused-variable -Wno-error=cast-qual MCU_DIR = hw/mcu/nxp/lpcopen/lpc15xx/lpc_chip_15xx diff --git a/hw/bsp/lpc17/family.mk b/hw/bsp/lpc17/family.mk index d719a47b7..551eb9e62 100644 --- a/hw/bsp/lpc17/family.mk +++ b/hw/bsp/lpc17/family.mk @@ -13,7 +13,7 @@ CFLAGS += \ -DRTC_EV_SUPPORT=0 # lpc_types.h cause following errors -CFLAGS += -Wno-error=strict-prototypes -Wno-error=cast-qual +CFLAGS_GCC += -Wno-error=strict-prototypes -Wno-error=cast-qual # caused by freeRTOS port !! CFLAGS += -Wno-error=maybe-uninitialized diff --git a/hw/bsp/lpc18/family.mk b/hw/bsp/lpc18/family.mk index f120f63b2..87b831255 100644 --- a/hw/bsp/lpc18/family.mk +++ b/hw/bsp/lpc18/family.mk @@ -12,7 +12,7 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_LPC18XX # mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-qual +CFLAGS_GCC += -Wno-error=unused-parameter -Wno-error=cast-qual LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs diff --git a/hw/bsp/lpc40/family.mk b/hw/bsp/lpc40/family.mk index ef9fe57b2..06155c760 100644 --- a/hw/bsp/lpc40/family.mk +++ b/hw/bsp/lpc40/family.mk @@ -13,7 +13,7 @@ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_LPC40XX # mcu driver cause following warnings -CFLAGS += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=cast-qual +CFLAGS_GCC += -Wno-error=strict-prototypes -Wno-error=unused-parameter -Wno-error=cast-qual LDFLAGS_GCC += --specs=nosys.specs --specs=nano.specs diff --git a/hw/bsp/lpc43/family.mk b/hw/bsp/lpc43/family.mk index e1406aae7..4a2ba6ec3 100644 --- a/hw/bsp/lpc43/family.mk +++ b/hw/bsp/lpc43/family.mk @@ -5,14 +5,14 @@ include ${TOP}/${BOARD_PATH}/board.mk CPU_CORE ?= cortex-m4 CFLAGS += \ - -flto \ - -nostdlib \ -DCORE_M4 \ -D__USE_LPCOPEN \ -DCFG_TUSB_MCU=OPT_MCU_LPC43XX # mcu driver cause following warnings -CFLAGS += \ +CFLAGS_GCC += \ + -flto \ + -nostdlib \ -Wno-error=unused-parameter \ -Wno-error=cast-qual \ -Wno-error=incompatible-pointer-types \ diff --git a/hw/bsp/stm32f4/family.mk b/hw/bsp/stm32f4/family.mk index 51ff43a60..c3c41dc3f 100644 --- a/hw/bsp/stm32f4/family.mk +++ b/hw/bsp/stm32f4/family.mk @@ -1,6 +1,5 @@ UF2_FAMILY_ID = 0x57755a57 ST_FAMILY = f4 -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver diff --git a/hw/bsp/stm32u5/boards/b_u585i_iot2a/board.mk b/hw/bsp/stm32u5/boards/b_u585i_iot2a/board.mk index ae63afef3..0a2c47030 100644 --- a/hw/bsp/stm32u5/boards/b_u585i_iot2a/board.mk +++ b/hw/bsp/stm32u5/boards/b_u585i_iot2a/board.mk @@ -1,11 +1,9 @@ +MCU_VARIANT = stm32u585xx CFLAGS += \ -DSTM32U585xx \ # All source paths should be relative to the top level. LD_FILE = ${FAMILY_PATH}/linker/STM32U575xx_FLASH.ld -SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s - -MCU_VARIANT = stm32u585xx # For flash-jlink target JLINK_DEVICE = stm32u585zi diff --git a/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk index 072c595fb..0aba57ce4 100644 --- a/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk +++ b/hw/bsp/stm32u5/boards/stm32u545nucleo/board.mk @@ -1,11 +1,9 @@ +MCU_VARIANT = stm32u545xx CFLAGS += \ -DSTM32U545xx \ # All source paths should be relative to the top level. LD_FILE = ${FAMILY_PATH}/linker/STM32U545xx_FLASH.ld -SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u545xx.s - -MCU_VARIANT = stm32u545xx # For flash-jlink target JLINK_DEVICE = stm32u545re diff --git a/hw/bsp/stm32u5/boards/stm32u575eval/board.mk b/hw/bsp/stm32u5/boards/stm32u575eval/board.mk index fee56f2ba..4bc9fea10 100644 --- a/hw/bsp/stm32u5/boards/stm32u575eval/board.mk +++ b/hw/bsp/stm32u5/boards/stm32u575eval/board.mk @@ -1,11 +1,9 @@ +MCU_VARIANT = stm32u575xx CFLAGS += \ -DSTM32U575xx \ # All source paths should be relative to the top level. LD_FILE = ${FAMILY_PATH}/linker/STM32U575xx_FLASH.ld -SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s - -MCU_VARIANT = stm32u575xx # For flash-jlink target JLINK_DEVICE = stm32u575ai diff --git a/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk b/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk index c83ec3999..d09dc5c46 100644 --- a/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk +++ b/hw/bsp/stm32u5/boards/stm32u575nucleo/board.mk @@ -1,11 +1,9 @@ +MCU_VARIANT = stm32u575xx CFLAGS += \ -DSTM32U575xx \ # All source paths should be relative to the top level. LD_FILE = ${FAMILY_PATH}/linker/STM32U575xx_FLASH.ld -SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u575xx.s - -MCU_VARIANT = stm32u575xx # For flash-jlink target JLINK_DEVICE = stm32u575zi diff --git a/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk b/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk index 4bebe3330..c9fdbac1a 100644 --- a/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk +++ b/hw/bsp/stm32u5/boards/stm32u5a5nucleo/board.mk @@ -1,3 +1,4 @@ +MCU_VARIANT = stm32u5a5xx CFLAGS += \ -DSTM32U5A5xx \ -DHSE_VALUE=16000000UL \ @@ -5,8 +6,5 @@ CFLAGS += \ # All source paths should be relative to the top level. LD_FILE = ${BOARD_PATH}/STM32U5A5ZJTXQ_FLASH.ld -SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32u5a5xx.s - -MCU_VARIANT = stm32u5a5xx # For flash-jlink target JLINK_DEVICE = stm32u575zi diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk index 05fe4608a..7fc728dcf 100644 --- a/hw/bsp/stm32u5/family.mk +++ b/hw/bsp/stm32u5/family.mk @@ -57,5 +57,12 @@ INC += \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/$(BOARD_PATH) +# Startup +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_$(MCU_VARIANT).s +SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT).s + +# Linker +LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash.icf + # flash target using on-board stlink flash: flash-stlink diff --git a/hw/bsp/stm32wb/family.mk b/hw/bsp/stm32wb/family.mk index de8372eea..a80ff6f5b 100644 --- a/hw/bsp/stm32wb/family.mk +++ b/hw/bsp/stm32wb/family.mk @@ -9,14 +9,12 @@ include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m4 CFLAGS += \ - -flto \ - -nostdlib -nostartfiles \ -DCFG_TUSB_MCU=OPT_MCU_STM32WB -# suppress warning caused by vendor mcu driver -CFLAGS += -Wno-error=cast-align -Wno-unused-parameter - -LD_FILE ?= ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_flash_cm4.ld +CFLAGS_GCC += \ + -flto \ + -nostdlib -nostartfiles \ + -Wno-error=cast-align -Wno-unused-parameter LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs @@ -25,19 +23,26 @@ SRC_C += \ $(ST_CMSIS)/Source/Templates/system_${ST_PREFIX}.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pwr.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pwr_ex.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_rcc.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_rcc_ex.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_uart.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_gpio.c -SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_${MCU_VARIANT}_cm4.s - INC += \ $(TOP)/$(BOARD_PATH) \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc +# Startup +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_$(MCU_VARIANT)_cm4.s +SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT)_cm4.s + +# Linker +LD_FILE_GCC ?= ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_flash_cm4.ld +LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash_cm4.icf + # flash target using on-board stlink flash: flash-stlink diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 6670045aa..87c77c9a7 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -344,7 +344,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t msc_csw_t * p_csw = &p_msc->csw; switch (p_msc->stage) { - case MSC_STAGE_CMD: + case MSC_STAGE_CMD: { //------------- new CBW received -------------// // Complete IN while waiting for CMD is usually Status of previous SCSI op, ignore it if (ep_addr != p_msc->ep_out) { @@ -441,7 +441,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t } } } - break; + break; + } case MSC_STAGE_DATA: TU_LOG_DRV(" SCSI Data [Lun%u]\r\n", p_cbw->lun); From 9eb0ae7636d816545696575837c3bcb4a93029d4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Apr 2025 15:15:07 +0700 Subject: [PATCH 123/382] fix iar make build with stm32 l0, f2, f3, u5, wb --- examples/device/cdc_msc/src/msc_disk.c | 193 +++++++----------- .../device/msc_dual_lun/src/msc_disk_dual.c | 29 +-- .../stm32f2/boards/stm32f207nucleo/board.mk | 7 +- hw/bsp/stm32f2/family.mk | 13 +- hw/bsp/stm32f3/boards/stm32f303disco/board.mk | 4 +- hw/bsp/stm32f3/family.mk | 18 +- hw/bsp/stm32l0/boards/stm32l052dap52/board.mk | 3 +- .../stm32l0/boards/stm32l0538disco/board.mk | 4 +- hw/bsp/stm32l0/family.mk | 19 +- 9 files changed, 119 insertions(+), 171 deletions(-) diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index d325d77fa..9645f4bfc 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -40,17 +40,15 @@ static bool ejected = false; If you find any bugs or get any questions, feel free to file an\r\n\ issue at github.com/hathach/tinyusb" -enum -{ - DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount +enum { + DISK_BLOCK_NUM = 16,// 8KB is the smallest size that windows allow to mount DISK_BLOCK_SIZE = 512 }; #ifdef CFG_EXAMPLE_MSC_READONLY const #endif -uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = -{ +uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { //------------- Block0: Boot Sector -------------// // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; // sector_per_cluster = 1; reserved_sectors = 1; @@ -59,60 +57,59 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = // drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29; // filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "TinyUSB MSC"; // FAT magic code at offset 510-511 - { - 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, - 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' , - 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, +{ + 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, + 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T', 'i', 'n', 'y', 'U', + 'S', 'B', ' ', 'M', 'S', 'C', 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, - // Zero up to 2 last bytes of FAT magic code - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Zero up to 2 last bytes of FAT magic code + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA - }, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA}, //------------- Block1: FAT12 Table -------------// - { - 0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file +{ + 0xF8, 0xFF, 0xFF, 0xFF, 0x0F// // first 2 entries must be F8FF, third entry is cluster end of readme file }, //------------- Block2: Root Directory -------------// - { - // first entry is volume label - 'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // second entry is readme file - 'R' , 'E' , 'A' , 'D' , 'M' , 'E' , ' ' , ' ' , 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D, - 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00, - sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes) +{ + // first entry is volume label + 'T', 'i', 'n', 'y', 'U', 'S', 'B', ' ', 'M', 'S', 'C', 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // second entry is readme file + 'R', 'E', 'A', 'D', 'M', 'E', ' ', ' ', 'T', 'X', 'T', 0x20, 0x00, 0xC6, 0x52, 0x6D, + 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00, + sizeof(README_CONTENTS) - 1, 0x00, 0x00, 0x00// readme's files size (4 Bytes) }, //------------- Block3: Readme Content -------------// @@ -121,23 +118,21 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = // Invoked when received SCSI_CMD_INQUIRY // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively -void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) -{ +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) { (void) lun; const char vid[] = "TinyUSB"; const char pid[] = "Mass Storage"; const char rev[] = "1.0"; - memcpy(vendor_id , vid, strlen(vid)); - memcpy(product_id , pid, strlen(pid)); + memcpy(vendor_id, vid, strlen(vid)); + memcpy(product_id, pid, strlen(pid)); memcpy(product_rev, rev, strlen(rev)); } // Invoked when received Test Unit Ready command. // return true allowing host to read/write this LUN e.g SD card inserted -bool tud_msc_test_unit_ready_cb(uint8_t lun) -{ +bool tud_msc_test_unit_ready_cb(uint8_t lun) { (void) lun; // RAM disk is ready until ejected @@ -152,29 +147,24 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) // Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size // Application update block count and block size -void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) -{ +void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) { (void) lun; *block_count = DISK_BLOCK_NUM; - *block_size = DISK_BLOCK_SIZE; + *block_size = DISK_BLOCK_SIZE; } // Invoked when received Start Stop Unit command // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage // - Start = 1 : active mode, if load_eject = 1 : load disk storage -bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) -{ +bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) { (void) lun; (void) power_condition; - if ( load_eject ) - { - if (start) - { + if (load_eject) { + if (start) { // load disk storage - }else - { + } else { // unload disk storage ejected = true; } @@ -185,52 +175,51 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo // Callback invoked when received READ10 command. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. -int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) -{ +int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) { (void) lun; // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) { + if (lba >= DISK_BLOCK_NUM) { return -1; } // Check for overflow of offset + bufsize - if ( offset + bufsize > DISK_BLOCK_SIZE ) { + if (offset + bufsize > DISK_BLOCK_SIZE) { return -1; } - uint8_t const* addr = msc_disk[lba] + offset; + uint8_t const *addr = msc_disk[lba] + offset; memcpy(buffer, addr, bufsize); return (int32_t) bufsize; } -bool tud_msc_is_writable_cb (uint8_t lun) -{ +bool tud_msc_is_writable_cb(uint8_t lun) { (void) lun; -#ifdef CFG_EXAMPLE_MSC_READONLY + #ifdef CFG_EXAMPLE_MSC_READONLY return false; -#else + #else return true; -#endif + #endif } // Callback invoked when received WRITE10 command. // Process data in buffer to disk's storage and return number of written bytes -int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) -{ +int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) { (void) lun; // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) return -1; + if (lba >= DISK_BLOCK_NUM) return -1; -#ifndef CFG_EXAMPLE_MSC_READONLY - uint8_t* addr = msc_disk[lba] + offset; + #ifndef CFG_EXAMPLE_MSC_READONLY + uint8_t *addr = msc_disk[lba] + offset; memcpy(addr, buffer, bufsize); -#else - (void) lba; (void) offset; (void) buffer; -#endif + #else + (void) lba; + (void) offset; + (void) buffer; + #endif return (int32_t) bufsize; } @@ -238,42 +227,18 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE // - READ10 and WRITE10 has their own callbacks -int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) -{ - // read10 & write10 has their own callback and MUST not be handled here +int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) { + (void) buffer; + (void) bufsize; - void const* response = NULL; - int32_t resplen = 0; - - // most scsi handled is input - bool in_xfer = true; - - switch (scsi_cmd[0]) - { + switch (scsi_cmd[0]) { default: // Set Sense = Invalid Command Operation tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // negative means error -> tinyusb could stall and/or response with failed status - resplen = -1; - break; + return -1; } - - // return resplen must not larger than bufsize - if ( resplen > bufsize ) resplen = bufsize; - - if ( response && (resplen > 0) ) - { - if(in_xfer) - { - memcpy(buffer, response, (size_t) resplen); - }else - { - // SCSI output - } - } - - return (int32_t) resplen; } #endif diff --git a/examples/device/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c index b44b77c6c..1f7fb98c7 100644 --- a/examples/device/msc_dual_lun/src/msc_disk_dual.c +++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c @@ -55,8 +55,7 @@ If you find any bugs or get any questions, feel free to file an\r\n\ issue at github.com/hathach/tinyusb" -MSC_CONST uint8_t msc_disk0[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = -{ +MSC_CONST uint8_t msc_disk0[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { //------------- Block0: Boot Sector -------------// // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; // sector_per_cluster = 1; reserved_sectors = 1; @@ -283,9 +282,11 @@ bool tud_msc_is_writable_cb(uint8_t lun) { // Process data in buffer to disk's storage and return number of written bytes int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { // out of ramdisk - if (lba >= DISK_BLOCK_NUM) return -1; + if (lba >= DISK_BLOCK_NUM) { + return -1; + } -#if defined(CFG_EXAMPLE_MSC_READONLY) || defined(CFG_EXAMPLE_MSC_DUAL_READONLY) + #if defined(CFG_EXAMPLE_MSC_READONLY) || defined(CFG_EXAMPLE_MSC_DUAL_READONLY) (void) lun; (void) lba; (void) offset; @@ -302,11 +303,8 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE // - READ10 and WRITE10 has their own callbacks (MUST not be handled here) int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) { - void const* response = NULL; - int32_t resplen = 0; - - // most scsi handled is input - bool in_xfer = true; + (void) buffer; + (void) bufsize; switch (scsi_cmd[0]) { default: @@ -316,19 +314,6 @@ int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, u // negative means error -> tinyusb could stall and/or response with failed status return -1; } - - // return resplen must not larger than bufsize - if (resplen > bufsize) resplen = bufsize; - - if (response && (resplen > 0)) { - if (in_xfer) { - memcpy(buffer, response, (size_t) resplen); - } else { - // SCSI output - } - } - - return resplen; } #endif diff --git a/hw/bsp/stm32f2/boards/stm32f207nucleo/board.mk b/hw/bsp/stm32f2/boards/stm32f207nucleo/board.mk index ba185d199..6e681ef57 100644 --- a/hw/bsp/stm32f2/boards/stm32f207nucleo/board.mk +++ b/hw/bsp/stm32f2/boards/stm32f207nucleo/board.mk @@ -1,12 +1,9 @@ -CFLAGS += \ - -DSTM32F207xx \ +MCU_VARIANT = stm32f207xx +CFLAGS += -DSTM32F207xx # All source paths should be relative to the top level. LD_FILE = $(BOARD_PATH)/STM32F207ZGTx_FLASH.ld -SRC_S += \ - $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f207xx.s - # For flash-jlink target JLINK_DEVICE = stm32f207zg diff --git a/hw/bsp/stm32f2/family.mk b/hw/bsp/stm32f2/family.mk index 7af9a76a0..e8f02548d 100644 --- a/hw/bsp/stm32f2/family.mk +++ b/hw/bsp/stm32f2/family.mk @@ -1,5 +1,4 @@ ST_FAMILY = f2 - ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver @@ -14,11 +13,10 @@ CPU_CORE ?= cortex-m3 CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_STM32F2 +# mcu driver cause following warnings CFLAGS_GCC += \ -flto \ - -# mcu driver cause following warnings -CFLAGS_GCC += -Wno-error=sign-compare + -Wno-error=sign-compare LDFLAGS_GCC += \ -nostdlib -nostartfiles \ @@ -40,3 +38,10 @@ INC += \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/$(BOARD_PATH) + +# Startup +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_${MCU_VARIANT}.s +SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_${MCU_VARIANT}.s + +# Linker +LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf diff --git a/hw/bsp/stm32f3/boards/stm32f303disco/board.mk b/hw/bsp/stm32f3/boards/stm32f303disco/board.mk index e387f2d54..6b9a3e283 100644 --- a/hw/bsp/stm32f3/boards/stm32f303disco/board.mk +++ b/hw/bsp/stm32f3/boards/stm32f303disco/board.mk @@ -1,12 +1,10 @@ +MCU_VARIANT = stm32f303xc CFLAGS += \ -DSTM32F303xC \ # All source paths should be relative to the top level. LD_FILE = $(BOARD_PATH)/STM32F303VCTx_FLASH.ld -SRC_S += \ - $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f303xc.s - # For flash-jlink target JLINK_DEVICE = stm32f303vc diff --git a/hw/bsp/stm32f3/family.mk b/hw/bsp/stm32f3/family.mk index 4fe3aa99d..13734583a 100644 --- a/hw/bsp/stm32f3/family.mk +++ b/hw/bsp/stm32f3/family.mk @@ -1,22 +1,17 @@ ST_FAMILY = f3 - ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver -DEPS_SUBMODULES += \ - lib/CMSIS_5 \ - $(ST_CMSIS) \ - $(ST_HAL_DRIVER) - include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m4 CFLAGS += \ - -flto \ -DCFG_TUSB_MCU=OPT_MCU_STM32F3 # mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter +CFLAGS_GCC += \ + -flto \ + -Wno-error=unused-parameter LDFLAGS_GCC += \ -nostdlib -nostartfiles \ @@ -36,3 +31,10 @@ INC += \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc \ $(TOP)/$(BOARD_PATH) + +# Startup +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_${MCU_VARIANT}.s +SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_${MCU_VARIANT}.s + +# Linker +LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf diff --git a/hw/bsp/stm32l0/boards/stm32l052dap52/board.mk b/hw/bsp/stm32l0/boards/stm32l052dap52/board.mk index 0b1348474..e63b41f12 100644 --- a/hw/bsp/stm32l0/boards/stm32l052dap52/board.mk +++ b/hw/bsp/stm32l0/boards/stm32l052dap52/board.mk @@ -1,10 +1,9 @@ +MCU_VARIANT = stm32l052xx CFLAGS += \ -DSTM32L052xx LD_FILE = $(BOARD_PATH)/STM32L052K8Ux_FLASH.ld -SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l052xx.s - # For flash-jlink target JLINK_DEVICE = stm32l052k8 diff --git a/hw/bsp/stm32l0/boards/stm32l0538disco/board.mk b/hw/bsp/stm32l0/boards/stm32l0538disco/board.mk index deed519ba..f3e6978b0 100644 --- a/hw/bsp/stm32l0/boards/stm32l0538disco/board.mk +++ b/hw/bsp/stm32l0/boards/stm32l0538disco/board.mk @@ -1,12 +1,10 @@ +MCU_VARIANT = stm32l053xx CFLAGS += \ -DSTM32L053xx # All source paths should be relative to the top level. LD_FILE = $(BOARD_PATH)/STM32L053C8Tx_FLASH.ld -SRC_S += \ - $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l053xx.s - # For flash-jlink target JLINK_DEVICE = STM32L053R8 diff --git a/hw/bsp/stm32l0/family.mk b/hw/bsp/stm32l0/family.mk index fe7561fc2..921b1b413 100644 --- a/hw/bsp/stm32l0/family.mk +++ b/hw/bsp/stm32l0/family.mk @@ -1,9 +1,4 @@ ST_FAMILY = l0 -DEPS_SUBMODULES += \ - lib/CMSIS_5 \ - hw/mcu/st/cmsis_device_$(ST_FAMILY) \ - hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver - ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver @@ -11,20 +6,17 @@ include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m0plus CFLAGS += \ - -flto \ -DCFG_EXAMPLE_MSC_READONLY \ -DCFG_EXAMPLE_VIDEO_READONLY \ -DCFG_TUSB_MCU=OPT_MCU_STM32L0 # mcu driver cause following warnings CFLAGS_GCC += \ + -flto \ -Wno-error=unused-parameter \ -Wno-error=redundant-decls \ -Wno-error=cast-align \ - -ifeq ($(TOOLCHAIN),gcc) -CFLAGS_GCC += -Wno-error=maybe-uninitialized -endif + -Wno-error=maybe-uninitialized \ CFLAGS_CLANG += \ -Wno-error=parentheses-equality @@ -48,3 +40,10 @@ INC += \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc + +# Startup +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_${MCU_VARIANT}.s +SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_${MCU_VARIANT}.s + +# Linker +LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash.icf From 3851c7c97a2a743b63d879ab622dd267b4195f08 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Apr 2025 16:07:10 +0700 Subject: [PATCH 124/382] - run arm-iar using github action - add skip_ci.txt to family folder to skip boards in ci run --- .github/workflows/build.yml | 62 +++++++++++++-------- .github/workflows/build_util.yml | 2 + hw/bsp/rp2040/skip_ci.txt | 7 +++ hw/bsp/stm32h7/boards/stm32h743eval/board.h | 10 ++-- hw/bsp/stm32h7/family.c | 4 +- tools/build.py | 7 ++- 6 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 hw/bsp/rp2040/skip_ci.txt diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f42499ef7..6419efbe8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -110,35 +110,51 @@ jobs: one-per-family: true # --------------------------------------- - # Build IAR on HFP self-hosted + # Build IAR # Since IAR Token secret is not passed to forked PR, only build on PR from the same repo # --------------------------------------- arm-iar: if: github.repository_owner == 'hathach' && github.event_name == 'push' needs: set-matrix - runs-on: [self-hosted, Linux, X64, hifiphile] - env: - BUILD_ARGS: ${{ join(fromJSON(needs.set-matrix.outputs.json)['arm-iar'], ' ') }} - IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} - steps: - - name: Clean workspace - run: | - echo "Cleaning up previous run" - rm -rf "${{ github.workspace }}" - mkdir -p "${{ github.workspace }}" + uses: ./.github/workflows/build_util.yml + secrets: inherit + strategy: + fail-fast: false + matrix: + build-system: + - 'cmake' + with: + build-system: ${{ matrix.build-system }} + toolchain: 'arm-iar' + build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)['arm-iar']) }} + one-per-family: ${{ github.event_name == 'push' }} - - name: Toolchain version - run: | - iccarm --version - - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Get Dependencies - run: python3 tools/get_deps.py $BUILD_ARGS - - - name: Build - run: python3 tools/build.py --one-per-family --toolchain iar $BUILD_ARGS +# arm-iar: +# if: github.repository_owner == 'hathach' && github.event_name == 'push' +# needs: set-matrix +# runs-on: [self-hosted, Linux, X64, hifiphile] +# env: +# BUILD_ARGS: ${{ join(fromJSON(needs.set-matrix.outputs.json)['arm-iar'], ' ') }} +# IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} +# steps: +# - name: Clean workspace +# run: | +# echo "Cleaning up previous run" +# rm -rf "${{ github.workspace }}" +# mkdir -p "${{ github.workspace }}" +# +# - name: Toolchain version +# run: | +# iccarm --version +# +# - name: Checkout TinyUSB +# uses: actions/checkout@v4 +# +# - name: Get Dependencies +# run: python3 tools/get_deps.py $BUILD_ARGS +# +# - name: Build +# run: python3 tools/build.py --one-per-family --toolchain iar $BUILD_ARGS # --------------------------------------- # Zephyr diff --git a/.github/workflows/build_util.yml b/.github/workflows/build_util.yml index 2de68c6f3..a2c96f3c0 100644 --- a/.github/workflows/build_util.yml +++ b/.github/workflows/build_util.yml @@ -58,6 +58,8 @@ jobs: shell: bash - name: Build + env: + IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} run: | if [ "${{ inputs.toolchain }}" == "esp-idf" ]; then docker run --rm -v $PWD:/project -w /project espressif/idf:tinyusb python tools/build.py ${{ matrix.arg }} diff --git a/hw/bsp/rp2040/skip_ci.txt b/hw/bsp/rp2040/skip_ci.txt new file mode 100644 index 000000000..fe99c9f65 --- /dev/null +++ b/hw/bsp/rp2040/skip_ci.txt @@ -0,0 +1,7 @@ +# boards in this files are skipped when running CI with this family +adafruit_feather_rp2040_usb_host +adafruit_fruit_jam +adafruit_metro_rp2350 +feather_rp2040_max3421 +pico_sdk +raspberry_pi_pico_w diff --git a/hw/bsp/stm32h7/boards/stm32h743eval/board.h b/hw/bsp/stm32h7/boards/stm32h743eval/board.h index 334876e51..cb6d772e6 100644 --- a/hw/bsp/stm32h7/boards/stm32h743eval/board.h +++ b/hw/bsp/stm32h7/boards/stm32h743eval/board.h @@ -184,7 +184,7 @@ static MFXSTM32L152_Object_t mfx_obj = { 0 }; static MFXSTM32L152_IO_Mode_t* mfx_io = NULL; static uint32_t mfx_vbus_pin[2] = { MFXSTM32L152_GPIO_PIN_7, MFXSTM32L152_GPIO_PIN_9 }; -int32_t board_i2c_init(void) { +static int32_t board_i2c_init(void) { __HAL_RCC_I2C1_CLK_ENABLE(); __HAL_RCC_I2C1_FORCE_RESET(); __HAL_RCC_I2C1_RELEASE_RESET(); @@ -200,16 +200,16 @@ int32_t board_i2c_init(void) { return 0; } -int32_t board_i2c_deinit(void) { +static int32_t board_i2c_deinit(void) { return 0; } -int32_t i2c_readreg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { +static int32_t i2c_readreg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { TU_ASSERT (HAL_OK == HAL_I2C_Mem_Read(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000)); return 0; } -int32_t i2c_writereg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { +static int32_t i2c_writereg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { TU_ASSERT(HAL_OK == HAL_I2C_Mem_Write(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000)); return 0; } @@ -249,7 +249,7 @@ static inline void board_init2(void) { } // VBUS1 is actually controlled by USB3320C PHY (using dwc2 drivebus signal) -void board_vbus_set(uint8_t rhport, bool state) { +static void board_vbus_set(uint8_t rhport, bool state) { if (mfx_io) { mfx_io->IO_WritePin(&mfx_obj, mfx_vbus_pin[rhport], state); } diff --git a/hw/bsp/stm32h7/family.c b/hw/bsp/stm32h7/family.c index e5228b29b..f8723b0c7 100644 --- a/hw/bsp/stm32h7/family.c +++ b/hw/bsp/stm32h7/family.c @@ -80,7 +80,7 @@ void OTG_HS_IRQHandler(void) { } #ifdef TRACE_ETM -void trace_etm_init(void) { +static void trace_etm_init(void) { // H7 trace pin is PE2 to PE6 GPIO_InitTypeDef gpio_init; gpio_init.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6; @@ -94,7 +94,7 @@ void trace_etm_init(void) { DBGMCU->CR |= DBGMCU_CR_DBG_TRACECKEN | DBGMCU_CR_DBG_CKD1EN | DBGMCU_CR_DBG_CKD3EN; } #else - #define trace_etm_init() +#define trace_etm_init() #endif void board_init(void) { diff --git a/tools/build.py b/tools/build.py index 633d2b582..d28ddd929 100755 --- a/tools/build.py +++ b/tools/build.py @@ -182,9 +182,14 @@ def build_boards_list(boards, toolchain, build_system, build_flags_on): def build_family(family, toolchain, build_system, build_flags_on, one_per_family, boards): + skip_ci = ['pico_sdk'] + if os.getenv('GITHUB_ACTIONS') or os.getenv('CIRCLECI'): + skip_ci_file = Path(f"hw/bsp/{family}/skip_ci.txt") + if skip_ci_file.exists(): + skip_ci = skip_ci_file.read_text().split() all_boards = [] for entry in os.scandir(f"hw/bsp/{family}/boards"): - if entry.is_dir() and entry.name != 'pico_sdk': + if entry.is_dir() and not entry.name in skip_ci: all_boards.append(entry.name) all_boards.sort() From d4983acd3a207d9d81c2698e5f5d2ace9b88e016 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Apr 2025 16:41:22 +0700 Subject: [PATCH 125/382] github ci support setup/install iar toolchain --- .github/actions/setup_toolchain/action.yml | 2 -- .../actions/setup_toolchain/download/action.yml | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml index 7c1f92c1a..850a3a06f 100644 --- a/.github/actions/setup_toolchain/action.yml +++ b/.github/actions/setup_toolchain/action.yml @@ -28,7 +28,6 @@ runs: - name: Get Toolchain URL if: >- inputs.toolchain != 'arm-gcc' && - inputs.toolchain != 'arm-iar' && inputs.toolchain != 'esp-idf' id: set-toolchain-url run: | @@ -40,7 +39,6 @@ runs: - name: Download Toolchain if: >- inputs.toolchain != 'arm-gcc' && - inputs.toolchain != 'arm-iar' && inputs.toolchain != 'esp-idf' uses: ./.github/actions/setup_toolchain/download with: diff --git a/.github/actions/setup_toolchain/download/action.yml b/.github/actions/setup_toolchain/download/action.yml index 813197208..ce9643010 100644 --- a/.github/actions/setup_toolchain/download/action.yml +++ b/.github/actions/setup_toolchain/download/action.yml @@ -23,17 +23,25 @@ runs: if: steps.cache-toolchain-download.outputs.cache-hit != 'true' run: | mkdir -p ~/cache/${{ inputs.toolchain }} - wget --progress=dot:giga ${{ inputs.toolchain_url }} -O toolchain.tar.gz + if [[ ${{ inputs.toolchain }} == rx-gcc ]]; then - mv toolchain.tar.gz toolchain.run + wget --progress=dot:giga ${{ inputs.toolchain_url }} -O toolchain.run chmod +x toolchain.run ./toolchain.run -p ~/cache/${{ inputs.toolchain }}/gnurx -y + elif [[ ${{ inputs.toolchain }} == arm-iar ]]; then + wget --progress=dot:giga ${{ inputs.toolchain_url }} -O ~/cache/${{ inputs.toolchain }}/cxarm.deb else + wget --progress=dot:giga ${{ inputs.toolchain_url }} -O toolchain.tar.gz tar -C ~/cache/${{ inputs.toolchain }} -xaf toolchain.tar.gz fi shell: bash - - name: Set Toolchain Path + - name: Setup Toolchain run: | - echo >> $GITHUB_PATH `echo ~/cache/${{ inputs.toolchain }}/*/bin` + if [[ ${{ inputs.toolchain }} == arm-iar ]]; then + sudo apt-get install -y ~/cache/${{ inputs.toolchain }}/cxarm.deb + echo >> $GITHUB_PATH "/opt/iar/cxarm/arm/bin" + else + echo >> $GITHUB_PATH `echo ~/cache/${{ inputs.toolchain }}/*/bin` + fi shell: bash From 0220852a6e79b0ea33654f17dae56c1ca882ea60 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Apr 2025 16:58:26 +0700 Subject: [PATCH 126/382] - hil test max retry = 3 - fix h7 unused function --- hw/bsp/stm32h7/boards/stm32h743eval/board.h | 2 +- hw/bsp/stm32h7/family.mk | 4 +--- test/hil/hil_test.py | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/hw/bsp/stm32h7/boards/stm32h743eval/board.h b/hw/bsp/stm32h7/boards/stm32h743eval/board.h index cb6d772e6..7c3f6414a 100644 --- a/hw/bsp/stm32h7/boards/stm32h743eval/board.h +++ b/hw/bsp/stm32h7/boards/stm32h743eval/board.h @@ -249,7 +249,7 @@ static inline void board_init2(void) { } // VBUS1 is actually controlled by USB3320C PHY (using dwc2 drivebus signal) -static void board_vbus_set(uint8_t rhport, bool state) { +static void TU_ATTR_UNUSED board_vbus_set(uint8_t rhport, bool state) { if (mfx_io) { mfx_io->IO_WritePin(&mfx_obj, mfx_vbus_pin[rhport], state); } diff --git a/hw/bsp/stm32h7/family.mk b/hw/bsp/stm32h7/family.mk index 29b83cf7d..19a085424 100644 --- a/hw/bsp/stm32h7/family.mk +++ b/hw/bsp/stm32h7/family.mk @@ -45,11 +45,9 @@ CFLAGS += \ -DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} \ # GCC Flags -CFLAGS_GCC += \ - -flto \ - # suppress warning caused by vendor mcu driver CFLAGS_GCC += \ + -flto \ -Wno-error=cast-align \ -Wno-error=unused-parameter \ diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py index 14ab4e63a..f292bca15 100755 --- a/test/hil/hil_test.py +++ b/test/hil/hil_test.py @@ -543,7 +543,7 @@ def test_example(board, f1, example): print(f'Flashing {fw_name}.elf') # flash firmware. It may fail randomly, retry a few times - max_rety = 2 + max_rety = 3 for i in range(max_rety): ret = globals()[f'flash_{board["flasher"]["name"].lower()}'](board, fw_name) if ret.returncode == 0: From 46d2d4199ea31babbffff51f9eaa65eda81c659b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Apr 2025 17:26:36 +0700 Subject: [PATCH 127/382] run arm-iar with non-forked PR --- .circleci/config.yml | 2 +- .github/workflows/build.yml | 36 +++++----------------------------- .github/workflows/hil_test.yml | 2 +- 3 files changed, 7 insertions(+), 33 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a7ae6980f..0b11b50e4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,7 +30,7 @@ jobs: # only build IAR if not forked PR, since IAR token is not shared if [ -z $CIRCLE_PR_USERNAME ]; then - BUILDSYSTEM_TOOLCHAIN+=("make arm-iar") + BUILDSYSTEM_TOOLCHAIN+=("cmake arm-iar") fi RESOURCE_LARGE='["nrf", "imxrt", "stm32f4", "stm32h7"]' diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6419efbe8..7fb13af74 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -111,10 +111,11 @@ jobs: # --------------------------------------- # Build IAR - # Since IAR Token secret is not passed to forked PR, only build on PR from the same repo + # Since IAR Token secret is not passed to forked PR, only build non-forked PR with make. + # cmake is built by circle-ci. Due to IAR limit capacity, only build oe per family # --------------------------------------- arm-iar: - if: github.repository_owner == 'hathach' && github.event_name == 'push' + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false needs: set-matrix uses: ./.github/workflows/build_util.yml secrets: inherit @@ -122,39 +123,12 @@ jobs: fail-fast: false matrix: build-system: - - 'cmake' + - 'make' with: build-system: ${{ matrix.build-system }} toolchain: 'arm-iar' build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)['arm-iar']) }} - one-per-family: ${{ github.event_name == 'push' }} - -# arm-iar: -# if: github.repository_owner == 'hathach' && github.event_name == 'push' -# needs: set-matrix -# runs-on: [self-hosted, Linux, X64, hifiphile] -# env: -# BUILD_ARGS: ${{ join(fromJSON(needs.set-matrix.outputs.json)['arm-iar'], ' ') }} -# IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} -# steps: -# - name: Clean workspace -# run: | -# echo "Cleaning up previous run" -# rm -rf "${{ github.workspace }}" -# mkdir -p "${{ github.workspace }}" -# -# - name: Toolchain version -# run: | -# iccarm --version -# -# - name: Checkout TinyUSB -# uses: actions/checkout@v4 -# -# - name: Get Dependencies -# run: python3 tools/get_deps.py $BUILD_ARGS -# -# - name: Build -# run: python3 tools/build.py --one-per-family --toolchain iar $BUILD_ARGS + one-per-family: true # --------------------------------------- # Zephyr diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml index 257416213..0ad37ffce 100644 --- a/.github/workflows/hil_test.yml +++ b/.github/workflows/hil_test.yml @@ -90,7 +90,7 @@ jobs: # --------------------------------------- # Hardware in the loop (HIL) # self-hosted by HFP, build with IAR toolchain, for attached hardware checkout test/hil/hfp.json - # Since IAR Token secret is not passed to forked PR, only build on PR from the same repo + # Since IAR Token secret is not passed to forked PR, only build non-forked PR # --------------------------------------- hil-hfp: if: github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false From e8a84f90764f0f2603822f068a9961ceeade873d Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 14 Apr 2025 16:09:32 +0700 Subject: [PATCH 128/382] enum For string descriptor (langid, manufacturer product, serila): always get the first 2 bytes to determine the length first. otherwise, some device may have buffer overflow. --- .../boards/espressif_s3_devkitc/board.h | 2 +- hw/bsp/espressif/family.cmake | 2 +- src/common/tusb_debug.h | 6 +- src/host/usbh.c | 124 ++++++++++-------- 4 files changed, 76 insertions(+), 58 deletions(-) diff --git a/hw/bsp/espressif/boards/espressif_s3_devkitc/board.h b/hw/bsp/espressif/boards/espressif_s3_devkitc/board.h index 6d7a94668..d2483c84f 100644 --- a/hw/bsp/espressif/boards/espressif_s3_devkitc/board.h +++ b/hw/bsp/espressif/boards/espressif_s3_devkitc/board.h @@ -36,7 +36,7 @@ extern "C" { #endif -#define NEOPIXEL_PIN 48 +#define NEOPIXEL_PIN 38 #define BUTTON_PIN 0 #define BUTTON_STATE_ACTIVE 0 diff --git a/hw/bsp/espressif/family.cmake b/hw/bsp/espressif/family.cmake index daa12cdb4..b544689d9 100644 --- a/hw/bsp/espressif/family.cmake +++ b/hw/bsp/espressif/family.cmake @@ -34,6 +34,6 @@ endif () set(EXTRA_COMPONENT_DIRS "src" "${CMAKE_CURRENT_LIST_DIR}/boards" "${CMAKE_CURRENT_LIST_DIR}/components") # set SDKCONFIG for each IDF Target -set(SDKCONFIG ${CMAKE_SOURCE_DIR}/sdkconfig.${IDF_TARGET}) +set(SDKCONFIG ${CMAKE_BINARY_DIR}/sdkconfig) include($ENV{IDF_PATH}/tools/cmake/project.cmake) diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index 2e9f1d9cd..1d0c6f1ad 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -108,15 +108,13 @@ typedef struct { } tu_lookup_table_t; static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) { - tu_static char not_found[11]; - for(uint16_t i=0; icount; i++) { - if (p_table->items[i].key == key) return p_table->items[i].data; + if (p_table->items[i].key == key) { return p_table->items[i].data; } } // not found return the key value in hex + static char not_found[11]; snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key); - return not_found; } diff --git a/src/host/usbh.c b/src/host/usbh.c index e60db53da..157a7ab86 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1372,9 +1372,13 @@ enum { ENUM_HUB_CLEAR_RESET_2, ENUM_SET_ADDR, ENUM_GET_DEVICE_DESC, + ENUM_GET_STRING_LANGUAGE_ID_LEN, ENUM_GET_STRING_LANGUAGE_ID, + ENUM_GET_STRING_MANUFACTURER_LEN, ENUM_GET_STRING_MANUFACTURER, + ENUM_GET_STRING_PRODUCT_LEN, ENUM_GET_STRING_PRODUCT, + ENUM_GET_STRING_SERIAL_LEN, ENUM_GET_STRING_SERIAL, ENUM_GET_9BYTE_CONFIG_DESC, ENUM_GET_FULL_CONFIG_DESC, @@ -1416,6 +1420,9 @@ static void process_enumeration(tuh_xfer_t* xfer) { uint8_t const daddr = xfer->daddr; uintptr_t const state = xfer->user_data; usbh_device_t* dev = get_device(daddr); + if (daddr > 0) { + TU_ASSERT(dev,); + } uint16_t langid = 0x0409; // default is English switch (state) { @@ -1474,30 +1481,6 @@ static void process_enumeration(tuh_xfer_t* xfer) { break; } -#if 0 - case ENUM_RESET_2: - // TODO not used by now, but may be needed for some devices !? - // Reset device again before Set Address - TU_LOG_USBH("Port reset2 \r\n"); - if (_dev0.hub_addr == 0) { - // connected directly to roothub - hcd_port_reset( _dev0.rhport ); - tusb_time_delay_ms_api(RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since - // sof of controller may not running while resetting - hcd_port_reset_end(_dev0.rhport); - // TODO: fall through to SET ADDRESS, refactor later - } -#if CFG_TUH_HUB - else { - // after RESET_DELAY the hub_port_reset() already complete - TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, - process_enumeration, ENUM_HUB_GET_STATUS_2), ); - break; - } -#endif - TU_ATTR_FALLTHROUGH; -#endif - case ENUM_SET_ADDR: enum_request_set_addr((tusb_desc_device_t*) _usbh_epbuf.ctrl); break; @@ -1520,14 +1503,15 @@ static void process_enumeration(tuh_xfer_t* xfer) { // Get full device descriptor TU_LOG_USBH("Get Device Descriptor\r\n"); TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_epbuf.ctrl, sizeof(tusb_desc_device_t), - process_enumeration, ENUM_GET_STRING_LANGUAGE_ID),); + process_enumeration, ENUM_GET_STRING_LANGUAGE_ID_LEN),); break; } - case ENUM_GET_STRING_LANGUAGE_ID: { + // For string descriptor (langid, manufacturer, product, serila): always get the first 2 bytes + // to determine the length first. otherwise, some device may have buffer overflow. + case ENUM_GET_STRING_LANGUAGE_ID_LEN: { // save the received device descriptor - TU_ASSERT(dev,); - tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl; + tusb_desc_device_t const *desc_device = (tusb_desc_device_t const *) _usbh_epbuf.ctrl; dev->vid = desc_device->idVendor; dev->pid = desc_device->idProduct; dev->i_manufacturer = desc_device->iManufacturer; @@ -1535,50 +1519,88 @@ static void process_enumeration(tuh_xfer_t* xfer) { dev->i_serial = desc_device->iSerialNumber; dev->bNumConfigurations = desc_device->bNumConfigurations; - tuh_enum_descriptor_device_cb(daddr, desc_device); // callback + tuh_enum_descriptor_device_cb(daddr, desc_device);// callback - tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE, - process_enumeration, ENUM_GET_STRING_MANUFACTURER); + tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, 2, + process_enumeration, ENUM_GET_STRING_LANGUAGE_ID); break; } - case ENUM_GET_STRING_MANUFACTURER: { - TU_ASSERT(dev,); - const tusb_desc_string_t* desc_langid = (tusb_desc_string_t const*) _usbh_epbuf.ctrl; + case ENUM_GET_STRING_LANGUAGE_ID: { + const uint8_t str_len = xfer->buffer[0]; + tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, str_len, + process_enumeration, ENUM_GET_STRING_MANUFACTURER_LEN); + break; + } + + case ENUM_GET_STRING_MANUFACTURER_LEN: { + const tusb_desc_string_t* desc_langid = (const tusb_desc_string_t *) _usbh_epbuf.ctrl; if (desc_langid->bLength >= 4) { - langid = tu_le16toh(desc_langid->utf16le[0]); + langid = tu_le16toh(desc_langid->utf16le[0]); // previous request is langid } if (dev->i_manufacturer != 0) { - tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE, + tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, 2, + process_enumeration, ENUM_GET_STRING_MANUFACTURER); + break; + }else { + TU_ATTR_FALLTHROUGH; + } + } + + case ENUM_GET_STRING_MANUFACTURER: { + if (dev->i_manufacturer != 0) { + langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request + const uint8_t str_len = xfer->buffer[0]; + tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, str_len, + process_enumeration, ENUM_GET_STRING_PRODUCT_LEN); + break; + } else { + TU_ATTR_FALLTHROUGH; + } + } + + case ENUM_GET_STRING_PRODUCT_LEN: + if (dev->i_product != 0) { + if (state == ENUM_GET_STRING_PRODUCT_LEN) { + langid = tu_le16toh(xfer->setup->wIndex); // get langid from previous setup packet if not fall through + } + tuh_descriptor_get_string(daddr, dev->i_product, langid, _usbh_epbuf.ctrl, 2, process_enumeration, ENUM_GET_STRING_PRODUCT); break; } else { TU_ATTR_FALLTHROUGH; } - } case ENUM_GET_STRING_PRODUCT: { - TU_ASSERT(dev,); - if (state == ENUM_GET_STRING_PRODUCT) { - langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet - } if (dev->i_product != 0) { - tuh_descriptor_get_string(daddr, dev->i_product, 0x0409, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE, - process_enumeration, ENUM_GET_STRING_SERIAL); + langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request + const uint8_t str_len = xfer->buffer[0]; + tuh_descriptor_get_string(daddr, dev->i_product, langid, _usbh_epbuf.ctrl, str_len, + process_enumeration, ENUM_GET_STRING_SERIAL_LEN); break; } else { TU_ATTR_FALLTHROUGH; } } - case ENUM_GET_STRING_SERIAL: { - TU_ASSERT(dev,); - if (state == ENUM_GET_STRING_SERIAL) { - langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet - } + case ENUM_GET_STRING_SERIAL_LEN: if (dev->i_serial != 0) { - tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE, - process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC); + if (state == ENUM_GET_STRING_SERIAL_LEN) { + langid = tu_le16toh(xfer->setup->wIndex); // get langid from previous setup packet if not fall through + } + tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, 2, + process_enumeration, ENUM_GET_STRING_SERIAL); + break; + } else { + TU_ATTR_FALLTHROUGH; + } + + case ENUM_GET_STRING_SERIAL: { + if (dev->i_serial != 0) { + langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request + const uint8_t str_len = xfer->buffer[0]; + tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, str_len, + process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC); break; } else { TU_ATTR_FALLTHROUGH; @@ -1627,8 +1649,6 @@ static void process_enumeration(tuh_xfer_t* xfer) { case ENUM_CONFIG_DRIVER: { TU_LOG_USBH("Device configured\r\n"); - TU_ASSERT(dev,); - dev->configured = 1; // Parse configuration & set up drivers From 5c7ca2acad12c72112437b51fcdd9d5adf5fe985 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Apr 2025 12:07:08 +0700 Subject: [PATCH 129/382] change gh ci iar to push event --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7fb13af74..a0e4725ce 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -115,7 +115,7 @@ jobs: # cmake is built by circle-ci. Due to IAR limit capacity, only build oe per family # --------------------------------------- arm-iar: - if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false + if: github.event_name == 'push' && github.repository_owner == 'hathach' needs: set-matrix uses: ./.github/workflows/build_util.yml secrets: inherit From ba45625ea4fe57625059b90e5d2c0f4602818737 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Apr 2025 12:39:49 +0700 Subject: [PATCH 130/382] minor ci update --- .github/workflows/build.yml | 5 +++-- .github/workflows/ci_set_matrix.py | 7 ++++--- hw/bsp/espressif/boards/espressif_s2_devkitc/board.h | 10 ++++++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a0e4725ce..17d578e4d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -85,7 +85,7 @@ jobs: - 'msp430-gcc' - 'riscv-gcc' - 'rx-gcc' - - 'esp-idf' # build-system is ignored + - 'esp-idf' with: build-system: 'make' toolchain: ${{ matrix.toolchain }} @@ -115,7 +115,8 @@ jobs: # cmake is built by circle-ci. Due to IAR limit capacity, only build oe per family # --------------------------------------- arm-iar: - if: github.event_name == 'push' && github.repository_owner == 'hathach' + if: false # disable for now since we got reach capacity limit too often + #if: github.event_name == 'push' && github.repository_owner == 'hathach' needs: set-matrix uses: ./.github/workflows/build_util.yml secrets: inherit diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index 410508246..fa73dc1b6 100755 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -44,9 +44,10 @@ family_list = { "stm32l0 stm32l4": ["arm-gcc", "arm-clang", "arm-iar"], "stm32u5 stm32wb": ["arm-gcc", "arm-clang", "arm-iar"], "xmc4000": ["arm-gcc"], - "-bespressif_kaluga_1": ["esp-idf"], - "-bespressif_s3_devkitm": ["esp-idf"], - "-bespressif_p4_function_ev": ["esp-idf"], + "-bespressif_s2_devkitc": ["esp-idf"], + # S3, P4 will be built by hil test + # "-bespressif_s3_devkitm": ["esp-idf"], + # "-bespressif_p4_function_ev": ["esp-idf"], } diff --git a/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h index 9c197591f..499a626a6 100644 --- a/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h +++ b/hw/bsp/espressif/boards/espressif_s2_devkitc/board.h @@ -36,13 +36,19 @@ extern "C" { #endif -// Note: On the production version (v1.2) WS2812 is connected to GPIO 18, -// however earlier revision v1.1 WS2812 is connected to GPIO 17 #define NEOPIXEL_PIN 18 #define BUTTON_PIN 0 #define BUTTON_STATE_ACTIVE 0 +// SPI for USB host shield +#define MAX3421_SPI_HOST SPI2_HOST +#define MAX3421_SCK_PIN 36 +#define MAX3421_MOSI_PIN 35 +#define MAX3421_MISO_PIN 37 +#define MAX3421_CS_PIN 15 +#define MAX3421_INTR_PIN 14 + #ifdef __cplusplus } #endif From 713410997326269b4072dce906933f8f44fd0efe Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 18 Apr 2025 11:12:14 +0200 Subject: [PATCH 131/382] Update hcd_edpt_open() note. Signed-off-by: HiFiPhile --- src/portable/template/hcd_template.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/portable/template/hcd_template.c b/src/portable/template/hcd_template.c index 694fa8550..fd870c91e 100644 --- a/src/portable/template/hcd_template.c +++ b/src/portable/template/hcd_template.c @@ -118,8 +118,8 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const (void) dev_addr; // NOTE: ep_desc is allocated on the stack when called from usbh_edpt_control_open() - // If you need to persist any ep_desc values across HCD calls (eg ep_desc->wMaxPacketSize), - // then you need to copy the data into another variable inside this function. + // You need to copy the data into a local variable who maintains the state of the endpoint and transfer. + // Check _hcd_data in hcd_dwc2.c for example. (void) ep_desc; return false; From 1b888a3311f1c722978d3bcb8ee0f5d5d4debd55 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Apr 2025 16:17:35 +0700 Subject: [PATCH 132/382] clean up, remove halted_sof_schedule flags since channel_xfer_in_retry() is only called when channel is halted. --- src/portable/synopsys/dwc2/hcd_dwc2.c | 48 +++++++++++---------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index d2070e57c..a95cc5e10 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -95,7 +95,6 @@ typedef struct { uint8_t err_count : 3; uint8_t period_split_nyet_count : 3; uint8_t halted_nyet : 1; - uint8_t halted_sof_schedule : 1; }; uint8_t result; @@ -713,19 +712,21 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { //-------------------------------------------------------------------- // HCD Event Handler //-------------------------------------------------------------------- + +// retry an IN transfer, channel must be halted static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hcint) { hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id]; - dwc2_channel_t* channel = &dwc2->channel[ch_id]; hcd_endpoint_t* edpt = &_hcd_data.edpt[xfer->ep_id]; + dwc2_channel_t* channel = &dwc2->channel[ch_id]; + dwc2_channel_char_t hcchar = {.value = channel->hcchar}; - if (channel_is_periodic(channel->hcchar)){ + if (channel_is_periodic(hcchar.value)){ const dwc2_channel_split_t hcsplt = {.value = channel->hcsplt}; // retry immediately for periodic split NYET if we haven't reach max retry if (hcsplt.split_en && hcsplt.split_compl && (hcint & HCINT_NYET || xfer->halted_nyet)) { xfer->period_split_nyet_count++; xfer->halted_nyet = 0; if (xfer->period_split_nyet_count < HCD_XFER_PERIOD_SPLIT_NYET_MAX) { - dwc2_channel_char_t hcchar = {.value = channel->hcchar}; hcchar.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame channel->hcchar = hcchar.value; channel_send_in_token(dwc2, channel); @@ -736,26 +737,20 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci } } - if (hcint & HCINT_HALTED) { - const uint32_t ucount = (hprt_speed_get(dwc2) == TUSB_SPEED_HIGH ? 1 : 8); - if (edpt->uframe_interval == ucount) { - // immediately retry if bInterval is 1 - edpt->hcchar_bm.odd_frame = 1 - (dwc2->hfnum & 1); // transfer on next frame - channel->hcchar = (edpt->hcchar & ~HCCHAR_CHENA); - channel_send_in_token(dwc2, channel); - } else { - // otherwise, de-allocate channel, enable SOF set frame counter for later transfer - const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; - edpt->next_pid = hctsiz.pid; // save PID - edpt->uframe_countdown = edpt->uframe_interval - ucount; - dwc2->gintmsk |= GINTSTS_SOF; - // already halted, de-allocate channel (called from DMA isr) - channel_dealloc(dwc2, ch_id); - } + const uint32_t ucount = (hprt_speed_get(dwc2) == TUSB_SPEED_HIGH ? 1 : 8); + if (edpt->uframe_interval == ucount) { + // retry on next frame if bInterval is 1 + hcchar.odd_frame = 1 - (dwc2->hfnum & 1); + channel->hcchar = hcchar.value; + channel_send_in_token(dwc2, channel); } else { - // disable channel first if not halted (called slave isr) - xfer->halted_sof_schedule = 1; - channel_disable(dwc2, channel); + // otherwise, de-allocate channel, enable SOF set frame counter for later transfer + const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; + edpt->next_pid = hctsiz.pid; // save PID + edpt->uframe_countdown = edpt->uframe_interval - ucount; + dwc2->gintmsk |= GINTSTS_SOF; + // already halted, de-allocate channel (called from DMA isr) + channel_dealloc(dwc2, ch_id); } } else { // for control/bulk: retry immediately @@ -905,7 +900,7 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h xfer->halted_nyet = 1; channel_disable(dwc2, channel); } else if (hcint & HCINT_NAK) { - // NAK received, re-enable channel if request queue is available + // NAK received, disable channel to flush all posted request and try again if (hcsplt.split_en) { hcsplt.split_compl = 0; // restart with start-split channel->hcsplt = hcsplt.value; @@ -937,10 +932,7 @@ static bool handle_channel_in_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t h } } else if (hcint & HCINT_HALTED) { channel->hcintmsk &= ~HCINT_HALTED; - if (xfer->halted_sof_schedule) { - // de-allocate channel but does not complete xfer, we schedule it in the SOF interrupt - channel_dealloc(dwc2, ch_id); - } else if (xfer->result != XFER_RESULT_INVALID) { + if (xfer->result != XFER_RESULT_INVALID) { is_done = true; } else if (xfer->err_count == HCD_XFER_ERROR_MAX) { xfer->result = XFER_RESULT_FAILED; From b7a26cc33c793a3fc03ee54e27f48d276405af0d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 18 Apr 2025 12:42:18 +0200 Subject: [PATCH 133/382] Fix 1st nak retry one frame shorter. Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index a68455daa..be653fab0 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -748,6 +748,7 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; edpt->next_pid = hctsiz.pid; // save PID edpt->uframe_countdown = edpt->uframe_interval - ucount; + dwc2->gintsts = GINTSTS_SOF; // SOF flag is probably pending dwc2->gintmsk |= GINTSTS_SOF; // already halted, de-allocate channel (called from DMA isr) channel_dealloc(dwc2, ch_id); From 8111e53ff067ca3a55f06389e4571fd57554ae5a Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Apr 2025 18:21:42 +0700 Subject: [PATCH 134/382] minor rename --- src/portable/synopsys/dwc2/hcd_dwc2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 1238a68e0..e1035fa55 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -75,9 +75,9 @@ typedef struct { struct TU_ATTR_PACKED { uint32_t uframe_interval : 18; // micro-frame interval - uint32_t speed : 2; - uint32_t next_pid : 2; - uint32_t do_ping : 1; + uint32_t speed : 2; + uint32_t next_pid : 2; // PID for next transfer + uint32_t next_do_ping : 1; // Do PING for next transfer if possible (highspeed OUT) // uint32_t : 9; }; @@ -567,12 +567,12 @@ static bool channel_xfer_start(dwc2_regs_t* dwc2, uint8_t ch_id) { hctsiz.pid = edpt->next_pid; // next PID is set in transfer complete interrupt hctsiz.packet_count = packet_count; hctsiz.xfer_size = edpt->buflen; - if (edpt->do_ping && edpt->speed == TUSB_SPEED_HIGH && + if (edpt->next_do_ping && edpt->speed == TUSB_SPEED_HIGH && edpt->next_pid != HCTSIZ_PID_SETUP && hcchar_bm->ep_dir == TUSB_DIR_OUT) { hctsiz.do_ping = 1; } channel->hctsiz = hctsiz.value; - edpt->do_ping = 0; + edpt->next_do_ping = 0; // pre-calculate next PID based on packet count, adjusted in transfer complete interrupt if short packet if (hcchar_bm->ep_num == 0) { @@ -970,7 +970,7 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t channel->hcsplt = hcsplt.value; channel->hcchar |= HCCHAR_CHENA; } else { - edpt->do_ping = 1; + edpt->next_do_ping = 1; channel_xfer_out_wrapup(dwc2, ch_id); channel_disable(dwc2, channel); } @@ -983,7 +983,7 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t channel->hcintmsk |= HCINT_ACK; } else { // NAK disable channel to flush all posted request and try again - edpt->do_ping = 1; + edpt->next_do_ping = 1; xfer->err_count = 0; } } else if (hcint & HCINT_HALTED) { @@ -1009,7 +1009,7 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t } } else { // Device is ready, resume transfer - edpt->do_ping = 0; + edpt->next_do_ping = 0; xfer->err_count = 0; TU_ASSERT(channel_xfer_start(dwc2, ch_id)); } From b3d20442e2252b95f674caf5572d7c392fefb080 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 18 Apr 2025 14:57:53 +0200 Subject: [PATCH 135/382] Fix usbh racing later. Signed-off-by: HiFiPhile --- src/host/usbh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 5ce325762..157a7ab86 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1038,7 +1038,7 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) // Check if dev0 is removed if ((event->rhport == _dev0.rhport) && (event->connection.hub_addr == _dev0.hub_addr) && (event->connection.hub_port == _dev0.hub_port)) { - //_dev0.enumerating = 0;// Causes assert in dwc2 process_enumeration() -> ENUM_ADDR0_DEVICE_DESC + _dev0.enumerating = 0; } break; From d51863d1a006f01f9d4ab9e9863dd6c6fdf8f13b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 18 Apr 2025 22:39:59 +0700 Subject: [PATCH 136/382] - correctly do_ping if received nyet as transfer complete e.g msc 31 byte command - correctly carry out OUT transfer when PING is ack --- src/portable/synopsys/dwc2/dwc2_type.h | 6 +++--- src/portable/synopsys/dwc2/hcd_dwc2.c | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/portable/synopsys/dwc2/dwc2_type.h b/src/portable/synopsys/dwc2/dwc2_type.h index 34e046346..0a8dacf5f 100644 --- a/src/portable/synopsys/dwc2/dwc2_type.h +++ b/src/portable/synopsys/dwc2/dwc2_type.h @@ -2088,9 +2088,9 @@ TU_VERIFY_STATIC(offsetof(dwc2_regs_t, fifo ) == 0x1000, "incorrect size"); #define HCTSIZ_DOPING_Pos (31U) #define HCTSIZ_DOPING_Msk (0x1UL << HCTSIZ_DOPING_Pos) // 0x80000000 #define HCTSIZ_DOPING HCTSIZ_DOPING_Msk // Do PING -#define HCTSIZ_PID_Pos (29U) -#define HCTSIZ_PID_Msk (0x3UL << HCTSIZ_PID_Pos) // 0x60000000 -#define HCTSIZ_PID HCTSIZ_PID_Msk // Data PID +#define HCTSIZ_PID_Pos (29U) +#define HCTSIZ_PID_Msk (0x3UL << HCTSIZ_PID_Pos) // 0x60000000 +#define HCTSIZ_PID HCTSIZ_PID_Msk // Data PID /******************** Bit definition for DIEPDMA register ********************/ #define DIEPDMA_DMAADDR_Pos (0U) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index e1035fa55..1845c5e19 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -959,6 +959,10 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t is_done = true; xfer->result = XFER_RESULT_SUCCESS; channel->hcintmsk &= ~HCINT_ACK; + if (hcint & HCINT_NYET) { + // complete transfer with NYET, do ping next time + edpt->next_do_ping = 1; + } } else if (hcint & HCINT_STALL) { xfer->result = XFER_RESULT_STALLED; channel_disable(dwc2, channel); @@ -1002,16 +1006,16 @@ static bool handle_channel_out_slave(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t channel->hcintmsk &= ~HCINT_ACK; if (hcsplt.split_en) { if (!hcsplt.split_compl) { - // start split is ACK --> do complete split + // ACK for start split --> do complete split hcsplt.split_compl = 1; channel->hcsplt = hcsplt.value; channel->hcchar |= HCCHAR_CHENA; } } else { - // Device is ready, resume transfer - edpt->next_do_ping = 0; - xfer->err_count = 0; - TU_ASSERT(channel_xfer_start(dwc2, ch_id)); + // ACK interrupt is only enabled for Split and PING + // ACK for PING, which mean device is ready to receive data + channel->hctsiz &= ~HCTSIZ_DOPING; // HC already cleared PING bit, but we clear anyway + channel->hcchar |= HCCHAR_CHENA; } } From b3a9b6e37ffb21dba2f6da5fdd4ac5cd90c94442 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 19 Apr 2025 11:43:28 +0200 Subject: [PATCH 137/382] enable SOF interrupt only if not already enabled Signed-off-by: HiFiPhile --- src/portable/synopsys/dwc2/hcd_dwc2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index be653fab0..378c2742b 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -748,8 +748,11 @@ static void channel_xfer_in_retry(dwc2_regs_t* dwc2, uint8_t ch_id, uint32_t hci const dwc2_channel_tsize_t hctsiz = {.value = channel->hctsiz}; edpt->next_pid = hctsiz.pid; // save PID edpt->uframe_countdown = edpt->uframe_interval - ucount; - dwc2->gintsts = GINTSTS_SOF; // SOF flag is probably pending - dwc2->gintmsk |= GINTSTS_SOF; + // enable SOF interrupt if not already enabled + if (!(dwc2->gintmsk & GINTMSK_SOFM)) { + dwc2->gintsts = GINTSTS_SOF; + dwc2->gintmsk |= GINTMSK_SOFM; + } // already halted, de-allocate channel (called from DMA isr) channel_dealloc(dwc2, ch_id); } From 5725d33121d483162730c7bb06cada3faf0da9af Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 21 Apr 2025 20:39:23 +0700 Subject: [PATCH 138/382] improve usbh stability with failed setup send, prevent control stage locked out --- src/host/usbh.c | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 157a7ab86..d6d974371 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -647,6 +647,21 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer) { *((xfer_result_t*) xfer->user_data) = xfer->result; } +TU_ATTR_ALWAYS_INLINE static inline void _control_set_xfer_stage(uint8_t stage) { + (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); + _ctrl_xfer.stage = stage; + (void) osal_mutex_unlock(_usbh_mutex); +} + +TU_ATTR_ALWAYS_INLINE static inline bool usbh_setup_send(uint8_t daddr, const uint8_t setup_packet[8]) { + const uint8_t rhport = usbh_get_rhport(daddr); + const bool ret = hcd_setup_send(rhport, daddr, setup_packet); + if (!ret) { + _control_set_xfer_stage(CONTROL_STAGE_IDLE); + } + return ret; +} + // TODO timeout_ms is not supported yet bool tuh_control_xfer (tuh_xfer_t* xfer) { TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); // EP0 with setup packet @@ -673,15 +688,13 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { (void) osal_mutex_unlock(_usbh_mutex); TU_VERIFY(is_idle); - const uint8_t rhport = usbh_get_rhport(daddr); - TU_LOG_USBH("[%u:%u] %s: ", rhport, daddr, (xfer->setup->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME) ? tu_str_std_request[xfer->setup->bRequest] : "Class Request"); TU_LOG_BUF_USBH(xfer->setup, 8); if (xfer->complete_cb) { - TU_ASSERT(hcd_setup_send(rhport, daddr, (uint8_t const *) &_usbh_epbuf.request)); + TU_ASSERT(usbh_setup_send(daddr, (uint8_t const *) &_usbh_epbuf.request)); }else { // blocking if complete callback is not provided // change callback to internal blocking, and result as user argument @@ -691,7 +704,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { _ctrl_xfer.user_data = (uintptr_t) &result; _ctrl_xfer.complete_cb = _control_blocking_complete_cb; - TU_ASSERT(hcd_setup_send(rhport, daddr, (uint8_t *) &_usbh_epbuf.request)); + TU_ASSERT(usbh_setup_send(daddr, (uint8_t const *) &_usbh_epbuf.request)); while (result == XFER_RESULT_INVALID) { // Note: this can be called within an callback ie. part of tuh_task() @@ -713,12 +726,6 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { return true; } -TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) { - (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); - _ctrl_xfer.stage = stage; - (void) osal_mutex_unlock(_usbh_mutex); -} - static void _control_xfer_complete(uint8_t daddr, xfer_result_t result) { TU_LOG_USBH("\r\n"); @@ -735,7 +742,7 @@ static void _control_xfer_complete(uint8_t daddr, xfer_result_t result) { .user_data = _ctrl_xfer.user_data }; - _set_control_xfer_stage(CONTROL_STAGE_IDLE); + _control_set_xfer_stage(CONTROL_STAGE_IDLE); if (xfer_temp.complete_cb) { xfer_temp.complete_cb(&xfer_temp); @@ -764,7 +771,7 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t _ctrl_xfer.actual_len = 0; // reset actual_len (void) osal_mutex_unlock(_usbh_mutex); - TU_ASSERT(hcd_setup_send(rhport, daddr, (uint8_t const *) request)); + TU_ASSERT(usbh_setup_send(daddr, (uint8_t const *) request)); } else { TU_LOG_USBH("[%u:%u] Control FAILED, xferred_bytes = %" PRIu32 "\r\n", rhport, daddr, xferred_bytes); TU_LOG_BUF_USBH(request, 8); @@ -777,8 +784,8 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t case CONTROL_STAGE_SETUP: if (request->wLength) { // DATA stage: initial data toggle is always 1 - _set_control_xfer_stage(CONTROL_STAGE_DATA); - TU_ASSERT( hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) ); + _control_set_xfer_stage(CONTROL_STAGE_DATA); + TU_ASSERT(hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength)); return true; } TU_ATTR_FALLTHROUGH; @@ -792,7 +799,7 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t _ctrl_xfer.actual_len = (uint16_t) xferred_bytes; // ACK stage: toggle is always 1 - _set_control_xfer_stage(CONTROL_STAGE_ACK); + _control_set_xfer_stage(CONTROL_STAGE_ACK); TU_ASSERT( hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, 1 - request->bmRequestType_bit.direction), NULL, 0) ); break; @@ -854,7 +861,7 @@ bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) { // control transfer: only 1 control at a time, check if we are aborting the current one TU_VERIFY(daddr == _ctrl_xfer.daddr && _ctrl_xfer.stage != CONTROL_STAGE_IDLE); hcd_edpt_abort_xfer(rhport, daddr, ep_addr); - _set_control_xfer_stage(CONTROL_STAGE_IDLE); // reset control transfer state to idle + _control_set_xfer_stage(CONTROL_STAGE_IDLE); // reset control transfer state to idle } else { usbh_device_t* dev = get_device(daddr); TU_VERIFY(dev); @@ -1321,7 +1328,9 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu clear_device(dev); // abort on-going control xfer on this device if any - if (_ctrl_xfer.daddr == daddr) _set_control_xfer_stage(CONTROL_STAGE_IDLE); + if (_ctrl_xfer.daddr == daddr) { + _control_set_xfer_stage(CONTROL_STAGE_IDLE); + } } } From 9f096ac56b637423ba7c4a4004f6f95006c12e95 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 12 Apr 2025 20:00:00 +0200 Subject: [PATCH 139/382] host: fix enumerate racing - if a previous enumeration failed _ctrl_xfer status could stuck, it needs to be cleared before next attempt. - after _dev0.enumerating is reset in hcd_event_handler(), if an attach event arrived before _ctrl_xfer clean up in remove event, a racing condition will happen. Signed-off-by: HiFiPhile --- src/host/usbh.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index d6d974371..69784ed47 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -311,6 +311,12 @@ TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) return &_usbh_devices[dev_addr-1]; } +TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) { + (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); + _ctrl_xfer.stage = stage; + (void) osal_mutex_unlock(_usbh_mutex); +} + static bool enum_new_device(hcd_event_t* event); static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); @@ -557,6 +563,13 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); process_removing_device(event.rhport, event.connection.hub_addr, event.connection.hub_port); + if ((event.rhport == _dev0.rhport) && (event.connection.hub_addr == _dev0.hub_addr) && + (event.connection.hub_port == _dev0.hub_port)) { + _dev0.enumerating = 0; + if (_ctrl_xfer.daddr == 0) { + _set_control_xfer_stage(CONTROL_STAGE_IDLE); + } + } #if CFG_TUH_HUB // TODO remove if (event.connection.hub_addr != 0 && event.connection.hub_port != 0) { @@ -1042,11 +1055,6 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) // FIXME device remove from a hub need an HCD API for hcd to free up endpoint // mark device as removing to prevent further xfer before the event is processed in usbh task - // Check if dev0 is removed - if ((event->rhport == _dev0.rhport) && (event->connection.hub_addr == _dev0.hub_addr) && - (event->connection.hub_port == _dev0.hub_port)) { - _dev0.enumerating = 0; - } break; default: break; From 3c4e6a779d65ad2d28e0eef0284df88e39bec6bc Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 18 Apr 2025 17:41:41 +0200 Subject: [PATCH 140/382] Move decouncing delay before USB reset. Signed-off-by: HiFiPhile --- src/host/usbh.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 69784ed47..c38afa3be 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1692,6 +1692,15 @@ static bool enum_new_device(hcd_event_t* event) { _dev0.hub_port = event->connection.hub_port; if (_dev0.hub_addr == 0) { + // wait until device connection is stable TODO non blocking + tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); + + // device unplugged while delaying + if (!hcd_port_connect_status(_dev0.rhport)) { + enum_full_complete(); + return true; + } + // connected directly to roothub hcd_port_reset(_dev0.rhport); @@ -1701,9 +1710,6 @@ static bool enum_new_device(hcd_event_t* event) { hcd_port_reset_end(_dev0.rhport); - // wait until device connection is stable TODO non blocking - tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); - // device unplugged while delaying if (!hcd_port_connect_status(_dev0.rhport)) { enum_full_complete(); From 7ba63a63022ed5ed2e92daca1cd011dd55547d39 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 18 Apr 2025 17:47:53 +0200 Subject: [PATCH 141/382] Also cleanup unaddressed device. Signed-off-by: HiFiPhile --- src/host/usbh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/host/usbh.c b/src/host/usbh.c index c38afa3be..712f10f0d 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -566,6 +566,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { if ((event.rhport == _dev0.rhport) && (event.connection.hub_addr == _dev0.hub_addr) && (event.connection.hub_port == _dev0.hub_port)) { _dev0.enumerating = 0; + hcd_device_close(_dev0.rhport, _dev0.hub_addr); if (_ctrl_xfer.daddr == 0) { _set_control_xfer_stage(CONTROL_STAGE_IDLE); } From 940fe43e68eaa6d8c38404410896574ed8147421 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 22 Apr 2025 17:33:37 +0700 Subject: [PATCH 142/382] move removing dev0 to process_removing_device() --- src/host/usbh.c | 59 ++++++++++++++++--------------------------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 712f10f0d..0a78177ea 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -311,12 +311,6 @@ TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) return &_usbh_devices[dev_addr-1]; } -TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) { - (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); - _ctrl_xfer.stage = stage; - (void) osal_mutex_unlock(_usbh_mutex); -} - static bool enum_new_device(hcd_event_t* event); static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); @@ -563,14 +557,6 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); process_removing_device(event.rhport, event.connection.hub_addr, event.connection.hub_port); - if ((event.rhport == _dev0.rhport) && (event.connection.hub_addr == _dev0.hub_addr) && - (event.connection.hub_port == _dev0.hub_port)) { - _dev0.enumerating = 0; - hcd_device_close(_dev0.rhport, _dev0.hub_addr); - if (_ctrl_xfer.daddr == 0) { - _set_control_xfer_stage(CONTROL_STAGE_IDLE); - } - } #if CFG_TUH_HUB // TODO remove if (event.connection.hub_addr != 0 && event.connection.hub_port != 0) { @@ -662,9 +648,11 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer) { } TU_ATTR_ALWAYS_INLINE static inline void _control_set_xfer_stage(uint8_t stage) { - (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); - _ctrl_xfer.stage = stage; - (void) osal_mutex_unlock(_usbh_mutex); + if (_ctrl_xfer.stage != stage) { + (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); + _ctrl_xfer.stage = stage; + (void) osal_mutex_unlock(_usbh_mutex); + } } TU_ATTR_ALWAYS_INLINE static inline bool usbh_setup_send(uint8_t daddr, const uint8_t setup_packet[8]) { @@ -1279,30 +1267,19 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { return (CFG_TUH_HUB > 0) && (daddr > CFG_TUH_DEVICE_MAX); } -//static void mark_removing_device_isr(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { -// for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { -// usbh_device_t *dev = &_usbh_devices[dev_id]; -// uint8_t const daddr = dev_id + 1; -// -// // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub -// if (dev->rhport == rhport && dev->connected && -// (hub_addr == 0 || dev->hub_addr == hub_addr) && -// (hub_port == 0 || dev->hub_port == hub_port)) { -// if (is_hub_addr(daddr)) { -// // If the device itself is a usb hub, mark all downstream devices. -// // FIXME recursive calls -// mark_removing_device_isr(rhport, daddr, 0); -// } -// -// dev->removing = 1; -// } -// } -//} - // a device unplugged from rhport:hub_addr:hub_port static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { + // dev0 is unplugged + if (_dev0.enumerating && (rhport == _dev0.rhport) && (hub_addr == _dev0.hub_addr) && (hub_port == _dev0.hub_port)) { + hcd_device_close(_dev0.rhport, 0); + if (_ctrl_xfer.daddr == 0) { + _control_set_xfer_stage(CONTROL_STAGE_IDLE); + } + _dev0.enumerating = 0; + return; + } + //------------- find the all devices (star-network) under port that is unplugged -------------// - // TODO mark as disconnected in ISR, also handle dev0 uint32_t removing_hubs = 0; do { for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { @@ -1343,9 +1320,11 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu } } - // if removing a hub, we need to remove its downstream devices + // if removing a hub, we need to remove all of its downstream devices #if CFG_TUH_HUB - if (removing_hubs == 0) break; + if (removing_hubs == 0) { + break; + } // find a marked hub to process for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) { From 8f9ef7dfbe41e29d4275be4ca2130d70d163f100 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 22 Apr 2025 22:09:06 +0700 Subject: [PATCH 143/382] reduce ENUM_DEBOUNCING_DELAY_MS to 200ms replace dev0.enumerating by enumerating_daddr for better clean up on unplugging while enumerating move controller_id & enumerating_daddr into _usbh_data struct --- src/host/usbh.c | 95 +++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 0a78177ea..bb4669718 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -96,12 +96,7 @@ typedef struct { uint8_t rhport; uint8_t hub_addr; uint8_t hub_port; - - struct TU_ATTR_PACKED { - uint8_t speed : 4; // packed speed to save footprint - volatile uint8_t enumerating : 1; // enumeration is in progress, false if not connected or all interfaces are configured - uint8_t TU_RESERVED : 3; - }; + uint8_t speed; } usbh_dev0_t; typedef struct { @@ -117,7 +112,6 @@ typedef struct { volatile uint8_t addressed : 1; // After SET_ADDR volatile uint8_t configured : 1; // After SET_CONFIG and all drivers are configured volatile uint8_t suspended : 1; // Bus suspended - // volatile uint8_t removing : 1; // Physically disconnected, waiting to be processed by usbh }; @@ -261,8 +255,6 @@ static inline usbh_class_driver_t const *get_driver(uint8_t drv_id) { // sum of end device + hub #define TOTAL_DEVICES (CFG_TUH_DEVICE_MAX + CFG_TUH_HUB) -static uint8_t _usbh_controller = TUSB_INDEX_INVALID_8; - // Device with address = 0 for enumeration static usbh_dev0_t _dev0; @@ -279,8 +271,7 @@ static usbh_device_t _usbh_devices[TOTAL_DEVICES]; #define _usbh_mutex NULL #endif -// Event queue -// usbh_int_set is used as mutex in OS NONE config +// Event queue: usbh_int_set() is used as mutex in OS NONE config OSAL_QUEUE_DEF(usbh_int_set, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); static osal_queue_t _usbh_q; @@ -305,6 +296,15 @@ typedef struct { CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf; +typedef struct { + uint8_t controller_id; // controller ID + uint8_t enumerating_daddr; // device address of the device being enumerated +} usbh_data_t; + +static usbh_data_t _usbh_data = { + .controller_id = TUSB_INDEX_INVALID_8, +}; + //------------- Helper Function -------------// TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) { TU_VERIFY(dev_addr > 0 && dev_addr <= TOTAL_DEVICES, NULL); @@ -334,7 +334,7 @@ bool tuh_mounted(uint8_t dev_addr) { bool tuh_connected(uint8_t daddr) { if (daddr == 0) { - return _dev0.enumerating; // dev0 is connected if still enumerating + return _usbh_data.enumerating_daddr == 0; } else { const usbh_device_t* dev = get_device(daddr); return dev && dev->connected; @@ -359,7 +359,7 @@ tusb_speed_t tuh_speed_get(uint8_t dev_addr) { } bool tuh_rhport_is_active(uint8_t rhport) { - return _usbh_controller == rhport; + return _usbh_data.controller_id == rhport; } bool tuh_rhport_reset_bus(uint8_t rhport, bool active) { @@ -387,7 +387,7 @@ static void clear_device(usbh_device_t* dev) { } bool tuh_inited(void) { - return _usbh_controller != TUSB_INDEX_INVALID_8; + return _usbh_data.controller_id != TUSB_INDEX_INVALID_8; } bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { @@ -427,6 +427,9 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(_usbh_devices, sizeof(_usbh_devices)); tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer)); + _usbh_data.controller_id = TUSB_INDEX_INVALID_8; + _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; + for (uint8_t i = 0; i < TOTAL_DEVICES; i++) { clear_device(&_usbh_devices[i]); } @@ -442,7 +445,7 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { } // Init host controller - _usbh_controller = rhport; + _usbh_data.controller_id = rhport; TU_ASSERT(hcd_init(rhport, rh_init)); hcd_int_enable(rhport); @@ -457,7 +460,7 @@ bool tuh_deinit(uint8_t rhport) { // deinit host controller hcd_int_disable(rhport); hcd_deinit(rhport); - _usbh_controller = TUSB_INDEX_INVALID_8; + _usbh_data.controller_id = TUSB_INDEX_INVALID_8; // "unplug" all devices on this rhport (hub_addr = 0, hub_port = 0) process_removing_device(rhport, 0, 0); @@ -524,20 +527,19 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { switch (event.event_id) { case HCD_EVENT_DEVICE_ATTACH: - // due to the shared control buffer, we must complete enumerating one device before enumerating another one. + // due to the shared control buffer, we must fully complete enumerating one device first. // TODO better to have an separated queue for newly attached devices - if (_dev0.enumerating) { - // Some device can cause multiple duplicated attach events - // drop current enumerating and start over for a proper port reset - if (event.rhport == _dev0.rhport && event.connection.hub_addr == _dev0.hub_addr && - event.connection.hub_port == _dev0.hub_port) { + if (_usbh_data.enumerating_daddr != TUSB_INDEX_INVALID_8) { + if (event.rhport == _dev0.rhport && + event.connection.hub_addr == _dev0.hub_addr && event.connection.hub_port == _dev0.hub_port) { + // Some device can cause multiple duplicated attach events + // drop current enumerating and start over for a proper port reset // abort/cancel current enumeration and start new one TU_LOG1("[%u:] USBH Device Attach (duplicated)\r\n", event.rhport); tuh_edpt_abort_xfer(0, 0); enum_new_device(&event); } else { TU_LOG_USBH("[%u:] USBH Defer Attach until current enumeration complete\r\n", event.rhport); - bool is_empty = osal_queue_empty(_usbh_q); queue_event(&event, in_isr); @@ -548,7 +550,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { } } else { TU_LOG1("[%u:] USBH Device Attach\r\n", event.rhport); - _dev0.enumerating = 1; + _usbh_data.enumerating_daddr = 0; enum_new_device(&event); } break; @@ -668,7 +670,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool usbh_setup_send(uint8_t daddr, const ui bool tuh_control_xfer (tuh_xfer_t* xfer) { TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); // EP0 with setup packet const uint8_t daddr = xfer->daddr; - TU_VERIFY(tuh_connected(daddr)); // Check if device is still connected (enumerating for dev0) + TU_VERIFY(tuh_connected(daddr)); // pre-check to help reducing mutex lock TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE); @@ -895,9 +897,9 @@ uint8_t *usbh_get_enum_buf(void) { void usbh_int_set(bool enabled) { // TODO all host controller if multiple are used since they shared the same event queue if (enabled) { - hcd_int_enable(_usbh_controller); + hcd_int_enable(_usbh_data.controller_id); } else { - hcd_int_disable(_usbh_controller); + hcd_int_disable(_usbh_data.controller_id); } } @@ -906,7 +908,6 @@ void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr) { event.event_id = USBH_EVENT_FUNC_CALL; event.func_call.func = func; event.func_call.param = param; - queue_event(&event, in_isr); } @@ -1043,7 +1044,6 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) case HCD_EVENT_DEVICE_REMOVE: // FIXME device remove from a hub need an HCD API for hcd to free up endpoint // mark device as removing to prevent further xfer before the event is processed in usbh task - break; default: break; @@ -1270,12 +1270,13 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { // a device unplugged from rhport:hub_addr:hub_port static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { // dev0 is unplugged - if (_dev0.enumerating && (rhport == _dev0.rhport) && (hub_addr == _dev0.hub_addr) && (hub_port == _dev0.hub_port)) { + if ((_usbh_data.enumerating_daddr == 0) && (rhport == _dev0.rhport) && + (hub_addr == _dev0.hub_addr) && (hub_port == _dev0.hub_port)) { hcd_device_close(_dev0.rhport, 0); if (_ctrl_xfer.daddr == 0) { _control_set_xfer_stage(CONTROL_STAGE_IDLE); } - _dev0.enumerating = 0; + _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; return; } @@ -1314,9 +1315,13 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu clear_device(dev); // abort on-going control xfer on this device if any - if (_ctrl_xfer.daddr == daddr) { + if (daddr == _ctrl_xfer.daddr) { _control_set_xfer_stage(CONTROL_STAGE_IDLE); } + + if (daddr == _usbh_data.enumerating_daddr) { + _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; + } } } @@ -1353,9 +1358,9 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu //--------------------------------------------------------------------+ enum { - ENUM_RESET_DELAY_MS = 50, // USB specs: 10 to 50ms - ENUM_DEBOUNCING_DELAY_MS = 450, // when plug/unplug a device, physical connection can be bouncing and may + ENUM_DEBOUNCING_DELAY_MS = 200, // when plug/unplug a device, physical connection can be bouncing and may // generate a series of attach/detach event. This delay wait for stable connection + ENUM_RESET_DELAY_MS = 50, // USB specs: 10 to 50ms }; enum { @@ -1399,7 +1404,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { // retry if not reaching max attempt failed_count++; - bool retry = _dev0.enumerating && (failed_count < ATTEMPT_COUNT_MAX); + bool retry = (_usbh_data.enumerating_daddr != TUSB_INDEX_INVALID_8) && (failed_count < ATTEMPT_COUNT_MAX); if (retry) { tusb_time_delay_ms_api(ATTEMPT_DELAY_MS); // delay a bit TU_LOG1("Enumeration attempt %u/%u\r\n", failed_count+1, ATTEMPT_COUNT_MAX); @@ -1409,7 +1414,6 @@ static void process_enumeration(tuh_xfer_t* xfer) { if (!retry) { enum_full_complete(); // complete as failed } - return; } failed_count = 0; @@ -1425,7 +1429,6 @@ static void process_enumeration(tuh_xfer_t* xfer) { switch (state) { #if CFG_TUH_HUB //case ENUM_HUB_GET_STATUS_1: break; - case ENUM_HUB_CLEAR_RESET_1: { hub_port_status_response_t port_status; memcpy(&port_status, _usbh_epbuf.ctrl, sizeof(hub_port_status_response_t)); @@ -1490,14 +1493,12 @@ static void process_enumeration(tuh_xfer_t* xfer) { usbh_device_t* new_dev = get_device(new_addr); TU_ASSERT(new_dev,); new_dev->addressed = 1; + _usbh_data.enumerating_daddr = new_addr; - // Close device 0 - hcd_device_close(_dev0.rhport, 0); + hcd_device_close(_dev0.rhport, 0); // close dev0 - // open control pipe for new address - TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->ep0_size),); + TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->ep0_size),); // open new control endpoint - // Get full device descriptor TU_LOG_USBH("Get Device Descriptor\r\n"); TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_epbuf.ctrl, sizeof(tusb_desc_device_t), process_enumeration, ENUM_GET_STRING_LANGUAGE_ID_LEN),); @@ -1516,8 +1517,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { dev->i_serial = desc_device->iSerialNumber; dev->bNumConfigurations = desc_device->bNumConfigurations; - tuh_enum_descriptor_device_cb(daddr, desc_device);// callback - + tuh_enum_descriptor_device_cb(daddr, desc_device); // callback tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, 2, process_enumeration, ENUM_GET_STRING_LANGUAGE_ID); break; @@ -1672,6 +1672,8 @@ static bool enum_new_device(hcd_event_t* event) { _dev0.hub_port = event->connection.hub_port; if (_dev0.hub_addr == 0) { + // connected directly to roothub + // wait until device connection is stable TODO non blocking tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); @@ -1681,8 +1683,7 @@ static bool enum_new_device(hcd_event_t* event) { return true; } - // connected directly to roothub - hcd_port_reset(_dev0.rhport); + hcd_port_reset(_dev0.rhport); // reset device // Since we are in middle of rhport reset, frame number is not available yet. // need to depend on tusb_time_millis_api() @@ -1905,7 +1906,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) { static void enum_full_complete(void) { // mark enumeration as complete - _dev0.enumerating = 0; + _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; #if CFG_TUH_HUB if (_dev0.hub_addr) { From 9645baa42ed3d50d650b9f2905a91d01b0a7a944 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 18 Apr 2025 12:16:35 +0200 Subject: [PATCH 144/382] include h7rs in host examples. Signed-off-by: HiFiPhile --- examples/host/bare_api/only.txt | 1 + examples/host/cdc_msc_hid/only.txt | 1 + examples/host/cdc_msc_hid_freertos/only.txt | 1 + examples/host/device_info/only.txt | 1 + examples/host/hid_controller/only.txt | 1 + examples/host/midi_rx/only.txt | 1 + examples/host/msc_file_explorer/only.txt | 1 + 7 files changed, 7 insertions(+) diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index 95f9f1d82..26662fc87 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -15,3 +15,4 @@ mcu:MAX3421 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32H7RS diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index 95f9f1d82..26662fc87 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -15,3 +15,4 @@ mcu:MAX3421 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32H7RS diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index e3ae25260..3bec7f7f1 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -13,3 +13,4 @@ mcu:MAX3421 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32H7RS diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index b6f87f423..dd2035421 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -18,3 +18,4 @@ mcu:RAXXX mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32H7RS diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt index 95f9f1d82..26662fc87 100644 --- a/examples/host/hid_controller/only.txt +++ b/examples/host/hid_controller/only.txt @@ -15,3 +15,4 @@ mcu:MAX3421 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32H7RS diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt index b6f87f423..dd2035421 100644 --- a/examples/host/midi_rx/only.txt +++ b/examples/host/midi_rx/only.txt @@ -18,3 +18,4 @@ mcu:RAXXX mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32H7RS diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index 95f9f1d82..26662fc87 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -15,3 +15,4 @@ mcu:MAX3421 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32H7RS From b6170c965f83a4f59ec7c165c502d812ceafea3f Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 22 Apr 2025 21:14:04 +0200 Subject: [PATCH 145/382] Compile fix. Signed-off-by: HiFiPhile --- src/host/usbh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index bb4669718..0492fb2f2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -692,7 +692,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { (void) osal_mutex_unlock(_usbh_mutex); TU_VERIFY(is_idle); - TU_LOG_USBH("[%u:%u] %s: ", rhport, daddr, + TU_LOG_USBH("[%u:%u] %s: ", usbh_get_rhport(daddr), daddr, (xfer->setup->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME) ? tu_str_std_request[xfer->setup->bRequest] : "Class Request"); TU_LOG_BUF_USBH(xfer->setup, 8); From 741cb3cf029e37682634eeb355c20420c0816c8d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 23 Apr 2025 12:35:32 +0700 Subject: [PATCH 146/382] rename hcd_devtree_info_t to tuh_bus_info_t, hcd_devtree_get_info to hcd_bus_info_get streamline bus info to usbh_devies, also replace dev0 (renamed to dev0_bus) --- .idea/debugServers/esp32s2.xml | 14 ++ .idea/debugServers/rp2350.xml | 2 +- .idea/debugServers/stm32f769.xml | 13 ++ .idea/debugServers/stm32h563.xml | 13 ++ .idea/debugServers/stm32h743.xml | 13 ++ examples/host/cdc_msc_hid/src/msc_app.c | 12 +- src/host/hcd.h | 12 +- src/host/usbh.c | 127 ++++++++---------- src/host/usbh_pvt.h | 2 +- src/portable/ehci/ehci.c | 10 +- src/portable/mentor/musb/hcd_musb.c | 24 ++-- src/portable/ohci/ohci.c | 6 +- .../raspberrypi/pio_usb/hcd_pio_usb.c | 6 +- src/portable/renesas/rusb2/hcd_rusb2.c | 6 +- src/portable/synopsys/dwc2/hcd_dwc2.c | 18 +-- 15 files changed, 152 insertions(+), 126 deletions(-) create mode 100644 .idea/debugServers/esp32s2.xml create mode 100644 .idea/debugServers/stm32f769.xml create mode 100644 .idea/debugServers/stm32h563.xml create mode 100644 .idea/debugServers/stm32h743.xml diff --git a/.idea/debugServers/esp32s2.xml b/.idea/debugServers/esp32s2.xml new file mode 100644 index 000000000..6a4aff3da --- /dev/null +++ b/.idea/debugServers/esp32s2.xml @@ -0,0 +1,14 @@ + + + + $USER_HOME$/.espressif/tools/xtensa-esp-elf-gdb/14.2_20240403/xtensa-esp-elf-gdb/bin/xtensa-esp32s2-elf-gdb + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/rp2350.xml b/.idea/debugServers/rp2350.xml index 5e092f3c4..52243a297 100644 --- a/.idea/debugServers/rp2350.xml +++ b/.idea/debugServers/rp2350.xml @@ -1,5 +1,5 @@ - + diff --git a/.idea/debugServers/stm32f769.xml b/.idea/debugServers/stm32f769.xml new file mode 100644 index 000000000..2fb322a0f --- /dev/null +++ b/.idea/debugServers/stm32f769.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/stm32h563.xml b/.idea/debugServers/stm32h563.xml new file mode 100644 index 000000000..9bf6db6e9 --- /dev/null +++ b/.idea/debugServers/stm32h563.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/stm32h743.xml b/.idea/debugServers/stm32h743.xml new file mode 100644 index 000000000..63680b78c --- /dev/null +++ b/.idea/debugServers/stm32h743.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/host/cdc_msc_hid/src/msc_app.c b/examples/host/cdc_msc_hid/src/msc_app.c index 1d7e18e6e..0e9c99766 100644 --- a/examples/host/cdc_msc_hid/src/msc_app.c +++ b/examples/host/cdc_msc_hid/src/msc_app.c @@ -30,13 +30,11 @@ //--------------------------------------------------------------------+ static scsi_inquiry_resp_t inquiry_resp; -bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) -{ +static bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_data) { msc_cbw_t const* cbw = cb_data->cbw; msc_csw_t const* csw = cb_data->csw; - if (csw->status != 0) - { + if (csw->status != 0) { printf("Inquiry failed\r\n"); return false; } @@ -55,16 +53,14 @@ bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const * cb_da } //------------- IMPLEMENTATION -------------// -void tuh_msc_mount_cb(uint8_t dev_addr) -{ +void tuh_msc_mount_cb(uint8_t dev_addr) { printf("A MassStorage device is mounted\r\n"); uint8_t const lun = 0; tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb, 0); } -void tuh_msc_umount_cb(uint8_t dev_addr) -{ +void tuh_msc_umount_cb(uint8_t dev_addr) { (void) dev_addr; printf("A MassStorage device is unmounted\r\n"); } diff --git a/src/host/hcd.h b/src/host/hcd.h index b20d96d54..1f2704a10 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -95,7 +95,7 @@ typedef struct { uint8_t hub_addr; uint8_t hub_port; uint8_t speed; -} hcd_devtree_info_t; +} tuh_bus_info_t; //--------------------------------------------------------------------+ // Memory API @@ -186,12 +186,8 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr); // USBH implemented API //--------------------------------------------------------------------+ -// Get device tree information of a device -// USB device tree can be complicated and manged by USBH, this help HCD to retrieve -// needed topology info to carry out its work -extern void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info); - -//------------- Event API -------------// +// Get device port information +extern bool hcd_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info); // Called by HCD to notify stack extern void hcd_event_handler(hcd_event_t const* event, bool in_isr); @@ -239,4 +235,4 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred } #endif -#endif /* _TUSB_HCD_H_ */ +#endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 0492fb2f2..c063c97f9 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -92,19 +92,7 @@ TU_ATTR_WEAK bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_si // USBH-HCD common data structure //--------------------------------------------------------------------+ typedef struct { - // port - uint8_t rhport; - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; -} usbh_dev0_t; - -typedef struct { - // port, must be same layout as usbh_dev0_t - uint8_t rhport; - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; + tuh_bus_info_t bus_info; // Device State struct TU_ATTR_PACKED { @@ -231,8 +219,8 @@ static usbh_class_driver_t const usbh_class_drivers[] = { enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) }; // Additional class drivers implemented by application -tu_static usbh_class_driver_t const * _app_driver = NULL; -tu_static uint8_t _app_driver_count = 0; +static usbh_class_driver_t const * _app_driver = NULL; +static uint8_t _app_driver_count = 0; #define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT) @@ -255,9 +243,6 @@ static inline usbh_class_driver_t const *get_driver(uint8_t drv_id) { // sum of end device + hub #define TOTAL_DEVICES (CFG_TUH_DEVICE_MAX + CFG_TUH_HUB) -// Device with address = 0 for enumeration -static usbh_dev0_t _dev0; - // all devices excluding zero-address // hub address start from CFG_TUH_DEVICE_MAX+1 // TODO: hub can has its own simpler struct to save memory @@ -299,6 +284,8 @@ CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf; typedef struct { uint8_t controller_id; // controller ID uint8_t enumerating_daddr; // device address of the device being enumerated + + tuh_bus_info_t dev0_bus; // bus info for dev0 in enumeration } usbh_data_t; static usbh_data_t _usbh_data = { @@ -353,9 +340,10 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid) { return true; } -tusb_speed_t tuh_speed_get(uint8_t dev_addr) { - usbh_device_t *dev = get_device(dev_addr); - return (tusb_speed_t) (dev ? get_device(dev_addr)->speed : _dev0.speed); +tusb_speed_t tuh_speed_get(uint8_t daddr) { + tuh_bus_info_t bus_info; + hcd_bus_info_get(daddr, &bus_info); + return bus_info.speed; } bool tuh_rhport_is_active(uint8_t rhport) { @@ -423,9 +411,9 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { } // Device - tu_memclr(&_dev0, sizeof(_dev0)); tu_memclr(_usbh_devices, sizeof(_usbh_devices)); tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer)); + tu_memclr(&_usbh_data, sizeof(_usbh_data)); _usbh_data.controller_id = TUSB_INDEX_INVALID_8; _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; @@ -530,8 +518,8 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { // due to the shared control buffer, we must fully complete enumerating one device first. // TODO better to have an separated queue for newly attached devices if (_usbh_data.enumerating_daddr != TUSB_INDEX_INVALID_8) { - if (event.rhport == _dev0.rhport && - event.connection.hub_addr == _dev0.hub_addr && event.connection.hub_port == _dev0.hub_port) { + if (event.rhport == _usbh_data.dev0_bus.rhport && + event.connection.hub_addr == _usbh_data.dev0_bus.hub_addr && event.connection.hub_port == _usbh_data.dev0_bus.hub_port) { // Some device can cause multiple duplicated attach events // drop current enumerating and start over for a proper port reset // abort/cancel current enumeration and start new one @@ -859,7 +847,7 @@ bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) { const uint8_t dir = tu_edpt_dir(ep_addr); if (epnum == 0) { - // Also include dev0 for aborting enumerating + // Also include dev0_bus for aborting enumerating const uint8_t rhport = usbh_get_rhport(daddr); // control transfer: only 1 control at a time, check if we are aborting the current one @@ -871,7 +859,7 @@ bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) { TU_VERIFY(dev); TU_VERIFY(dev->ep_status[epnum][dir].busy); // non-control skip if not busy - hcd_edpt_abort_xfer(dev->rhport, daddr, ep_addr); + hcd_edpt_abort_xfer(dev->bus_info.rhport, daddr, ep_addr); // mark as ready and release endpoint if transfer is aborted dev->ep_status[epnum][dir].busy = false; @@ -885,9 +873,10 @@ bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) { // USBH API For Class Driver //--------------------------------------------------------------------+ -uint8_t usbh_get_rhport(uint8_t dev_addr) { - usbh_device_t *dev = get_device(dev_addr); - return dev ? dev->rhport : _dev0.rhport; +uint8_t usbh_get_rhport(uint8_t daddr) { + tuh_bus_info_t bus_info; + hcd_bus_info_get(daddr, &bus_info); + return bus_info.rhport; } uint8_t *usbh_get_enum_buf(void) { @@ -972,7 +961,7 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t* bu dev->ep_callback[epnum][dir].user_data = user_data; #endif - if (hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes)) { + if (hcd_edpt_xfer(dev->bus_info.rhport, dev_addr, ep_addr, buffer, total_bytes)) { TU_LOG_USBH("OK\r\n"); return true; } else { @@ -1024,19 +1013,14 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) { // HCD Event Handler //--------------------------------------------------------------------+ -void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info) { - usbh_device_t const* dev = get_device(dev_addr); +bool hcd_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info) { + usbh_device_t const* dev = get_device(daddr); if (dev) { - devtree_info->rhport = dev->rhport; - devtree_info->hub_addr = dev->hub_addr; - devtree_info->hub_port = dev->hub_port; - devtree_info->speed = dev->speed; + *bus_info = dev->bus_info; } else { - devtree_info->rhport = _dev0.rhport; - devtree_info->hub_addr = _dev0.hub_addr; - devtree_info->hub_port = _dev0.hub_port; - devtree_info->speed = _dev0.speed; + *bus_info = _usbh_data.dev0_bus; } + return true; } TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) { @@ -1269,10 +1253,10 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { // a device unplugged from rhport:hub_addr:hub_port static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { - // dev0 is unplugged - if ((_usbh_data.enumerating_daddr == 0) && (rhport == _dev0.rhport) && - (hub_addr == _dev0.hub_addr) && (hub_port == _dev0.hub_port)) { - hcd_device_close(_dev0.rhport, 0); + // dev0_bus is unplugged + if ((_usbh_data.enumerating_daddr == 0) && (rhport == _usbh_data.dev0_bus.rhport) && + (hub_addr == _usbh_data.dev0_bus.hub_addr) && (hub_port == _usbh_data.dev0_bus.hub_port)) { + hcd_device_close(_usbh_data.dev0_bus.rhport, 0); if (_ctrl_xfer.daddr == 0) { _control_set_xfer_stage(CONTROL_STAGE_IDLE); } @@ -1288,9 +1272,9 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu uint8_t const daddr = dev_id + 1; // hub_addr = 0 means roothub, hub_port = 0 means all devices of downstream hub - if (dev->rhport == rhport && dev->connected && - (hub_addr == 0 || dev->hub_addr == hub_addr) && - (hub_port == 0 || dev->hub_port == hub_port)) { + if (dev->bus_info.rhport == rhport && dev->connected && + (hub_addr == 0 || dev->bus_info.hub_addr == hub_addr) && + (hub_port == 0 || dev->bus_info.hub_port == hub_port)) { TU_LOG_USBH("[%u:%u:%u] unplugged address = %u\r\n", rhport, hub_addr, hub_port, daddr); if (is_hub_addr(daddr)) { @@ -1439,12 +1423,12 @@ static void process_enumeration(tuh_xfer_t* xfer) { return; } - _dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : + _usbh_data.dev0_bus.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : (port_status.status.low_speed) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; // Acknowledge Port Reset Change if (port_status.change.reset) { - hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port, + hub_port_clear_reset_change(_usbh_data.dev0_bus.hub_addr, _usbh_data.dev0_bus.hub_port, process_enumeration, ENUM_ADDR0_DEVICE_DESC); } break; @@ -1452,7 +1436,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { case ENUM_HUB_GET_STATUS_2: tusb_time_delay_ms_api(ENUM_RESET_DELAY_MS); - TU_ASSERT(hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_epbuf.ctrl, + TU_ASSERT(hub_port_get_status(_usbh_data.dev0_bus.hub_addr, _usbh_data.dev0_bus.hub_port, _usbh_epbuf.ctrl, process_enumeration, ENUM_HUB_CLEAR_RESET_2),); break; @@ -1462,7 +1446,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { // Acknowledge Port Reset Change if Reset Successful if (port_status.change.reset) { - TU_ASSERT(hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port, + TU_ASSERT(hub_port_clear_reset_change(_usbh_data.dev0_bus.hub_addr, _usbh_data.dev0_bus.hub_port, process_enumeration, ENUM_SET_ADDR),); } break; @@ -1495,7 +1479,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { new_dev->addressed = 1; _usbh_data.enumerating_daddr = new_addr; - hcd_device_close(_dev0.rhport, 0); // close dev0 + hcd_device_close(_usbh_data.dev0_bus.rhport, 0); // close dev0_bus TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->ep0_size),); // open new control endpoint @@ -1667,38 +1651,38 @@ static void process_enumeration(tuh_xfer_t* xfer) { } static bool enum_new_device(hcd_event_t* event) { - _dev0.rhport = event->rhport; - _dev0.hub_addr = event->connection.hub_addr; - _dev0.hub_port = event->connection.hub_port; + _usbh_data.dev0_bus.rhport = event->rhport; + _usbh_data.dev0_bus.hub_addr = event->connection.hub_addr; + _usbh_data.dev0_bus.hub_port = event->connection.hub_port; - if (_dev0.hub_addr == 0) { + if (_usbh_data.dev0_bus.hub_addr == 0) { // connected directly to roothub // wait until device connection is stable TODO non blocking tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); // device unplugged while delaying - if (!hcd_port_connect_status(_dev0.rhport)) { + if (!hcd_port_connect_status(_usbh_data.dev0_bus.rhport)) { enum_full_complete(); return true; } - hcd_port_reset(_dev0.rhport); // reset device + hcd_port_reset(_usbh_data.dev0_bus.rhport); // reset device // Since we are in middle of rhport reset, frame number is not available yet. // need to depend on tusb_time_millis_api() tusb_time_delay_ms_api(ENUM_RESET_DELAY_MS); - hcd_port_reset_end(_dev0.rhport); + hcd_port_reset_end(_usbh_data.dev0_bus.rhport); // device unplugged while delaying - if (!hcd_port_connect_status(_dev0.rhport)) { + if (!hcd_port_connect_status(_usbh_data.dev0_bus.rhport)) { enum_full_complete(); return true; } - _dev0.speed = hcd_port_speed_get(_dev0.rhport); - TU_LOG_USBH("%s Speed\r\n", tu_str_speed[_dev0.speed]); + _usbh_data.dev0_bus.speed = hcd_port_speed_get(_usbh_data.dev0_bus.rhport); + TU_LOG_USBH("%s Speed\r\n", tu_str_speed[_usbh_data.dev0.speed]); // fake transfer to kick-off the enumeration process tuh_xfer_t xfer; @@ -1715,7 +1699,7 @@ static bool enum_new_device(hcd_event_t* event) { tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); // ENUM_HUB_GET_STATUS - TU_ASSERT(hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_epbuf.ctrl, + TU_ASSERT(hub_port_get_status(_usbh_data.dev0_bus.hub_addr, _usbh_data.dev0_bus.hub_port, _usbh_epbuf.ctrl, process_enumeration, ENUM_HUB_CLEAR_RESET_1)); } #endif // hub @@ -1749,10 +1733,7 @@ static bool enum_request_set_addr(tusb_desc_device_t const* desc_device) { TU_LOG_USBH("Set Address = %d\r\n", new_addr); usbh_device_t* new_dev = get_device(new_addr); - new_dev->rhport = _dev0.rhport; - new_dev->hub_addr = _dev0.hub_addr; - new_dev->hub_port = _dev0.hub_port; - new_dev->speed = _dev0.speed; + new_dev->bus_info = _usbh_data.dev0_bus; new_dev->connected = 1; new_dev->ep0_size = desc_device->bMaxPacketSize0; @@ -1768,7 +1749,7 @@ static bool enum_request_set_addr(tusb_desc_device_t const* desc_device) { .wLength = 0 }; tuh_xfer_t xfer = { - .daddr = 0, // dev0 + .daddr = 0, .ep_addr = 0, .setup = &request, .buffer = NULL, @@ -1841,7 +1822,7 @@ static bool enum_parse_configuration_desc(uint8_t dev_addr, tusb_desc_configurat // Find driver for this interface for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { usbh_class_driver_t const * driver = get_driver(drv_id); - if (driver && driver->open(dev->rhport, dev_addr, desc_itf, drv_len) ) { + if (driver && driver->open(dev->bus_info.rhport, dev_addr, desc_itf, drv_len) ) { // open successfully TU_LOG_USBH(" %s opened\r\n", driver->name); @@ -1860,9 +1841,9 @@ static bool enum_parse_configuration_desc(uint8_t dev_addr, tusb_desc_configurat break; // exit driver find loop } - if ( drv_id == TOTAL_DRIVER_COUNT - 1 ) { + if (drv_id == TOTAL_DRIVER_COUNT - 1) { TU_LOG_USBH("[%u:%u] Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", - dev->rhport, dev_addr, desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); + dev->bus_info.rhport, dev_addr, desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); } } @@ -1909,8 +1890,8 @@ static void enum_full_complete(void) { _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; #if CFG_TUH_HUB - if (_dev0.hub_addr) { - hub_edpt_status_xfer(_dev0.hub_addr); // get next hub status + if (_usbh_data.dev0_bus.hub_addr != 0) { + hub_edpt_status_xfer(_usbh_data.dev0_bus.hub_addr); // get next hub status } #endif diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index bfa1fb2ba..61b012493 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -63,7 +63,7 @@ usbh_class_driver_t const* usbh_app_driver_get_cb(uint8_t* driver_count) TU_ATTR // Call by class driver to tell USBH that it has complete the enumeration void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num); -uint8_t usbh_get_rhport(uint8_t dev_addr); +uint8_t usbh_get_rhport(uint8_t daddr); uint8_t* usbh_get_enum_buf(void); diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 7451f69a3..141a2c026 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -837,8 +837,8 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c tu_memclr(p_qhd, sizeof(ehci_qhd_t)); } - hcd_devtree_info_t devtree_info; - hcd_devtree_get_info(dev_addr, &devtree_info); + tuh_bus_info_t bus_info; + hcd_bus_info_get(dev_addr, &bus_info); uint8_t const xfer_type = ep_desc->bmAttributes.xfer; uint8_t const interval = ep_desc->bInterval; @@ -846,7 +846,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c p_qhd->dev_addr = dev_addr; p_qhd->fl_inactive_next_xact = 0; p_qhd->ep_number = tu_edpt_number(ep_desc->bEndpointAddress); - p_qhd->ep_speed = devtree_info.speed; + p_qhd->ep_speed = bus_info.speed; p_qhd->data_toggle_control= (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0; p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static async list head p_qhd->max_packet_size = tu_edpt_packet_size(ep_desc); @@ -887,8 +887,8 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c default: break; } - p_qhd->fl_hub_addr = devtree_info.hub_addr; - p_qhd->fl_hub_port = devtree_info.hub_port; + p_qhd->fl_hub_addr = bus_info.hub_addr; + p_qhd->fl_hub_port = bus_info.hub_port; p_qhd->mult = 1; // TODO not use high bandwidth/park mode yet //------------- HCD Management Data -------------// diff --git a/src/portable/mentor/musb/hcd_musb.c b/src/portable/mentor/musb/hcd_musb.c index 811043d74..97ef46152 100644 --- a/src/portable/mentor/musb/hcd_musb.c +++ b/src/portable/mentor/musb/hcd_musb.c @@ -695,16 +695,16 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet _hcd.pipe0.length = 8; _hcd.pipe0.remaining = 0; - hcd_devtree_info_t devtree; - hcd_devtree_get_info(dev_addr, &devtree); - switch (devtree.speed) { + tuh_bus_info_t bus_info; + hcd_bus_info_get(dev_addr, &bus_info); + switch (bus_info.speed) { default: return false; case TUSB_SPEED_LOW: USB0->TYPE0 = USB_TYPE0_SPEED_LOW; break; case TUSB_SPEED_FULL: USB0->TYPE0 = USB_TYPE0_SPEED_FULL; break; case TUSB_SPEED_HIGH: USB0->TYPE0 = USB_TYPE0_SPEED_HIGH; break; } - USB0->TXHUBADDR0 = devtree.hub_addr; - USB0->TXHUBPORT0 = devtree.hub_port; + USB0->TXHUBADDR0 = bus_info.hub_addr; + USB0->TXHUBPORT0 = bus_info.hub_port; USB0->TXFUNCADDR0 = dev_addr; USB0->CSRL0 = USB_CSRL0_TXRDY | USB_CSRL0_SETUP; return true; @@ -744,9 +744,9 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const pipe->remaining = 0; uint8_t pipe_type = 0; - hcd_devtree_info_t devtree; - hcd_devtree_get_info(dev_addr, &devtree); - switch (devtree.speed) { + tuh_bus_info_t bus_info; + hcd_bus_info_get(dev_addr, &bus_info); + switch (bus_info.speed) { default: return false; case TUSB_SPEED_LOW: pipe_type |= USB_TXTYPE1_SPEED_LOW; break; case TUSB_SPEED_FULL: pipe_type |= USB_TXTYPE1_SPEED_FULL; break; @@ -763,8 +763,8 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const hw_endpoint_t volatile *regs = edpt_regs(pipenum - 1); if (dir_tx) { fadr->TXFUNCADDR = dev_addr; - fadr->TXHUBADDR = devtree.hub_addr; - fadr->TXHUBPORT = devtree.hub_port; + fadr->TXHUBADDR = bus_info.hub_addr; + fadr->TXHUBPORT = bus_info.hub_port; regs->TXMAXP = mps; regs->TXTYPE = pipe_type | epn; regs->TXINTERVAL = ep_desc->bInterval; @@ -775,8 +775,8 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const USB0->TXIE |= TU_BIT(pipenum); } else { fadr->RXFUNCADDR = dev_addr; - fadr->RXHUBADDR = devtree.hub_addr; - fadr->RXHUBPORT = devtree.hub_port; + fadr->RXHUBADDR = bus_info.hub_addr; + fadr->RXHUBPORT = bus_info.hub_port; regs->RXMAXP = mps; regs->RXTYPE = pipe_type | epn; regs->RXINTERVAL = ep_desc->bInterval; diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index 672ad0443..465b6731c 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -328,13 +328,13 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t tu_memclr(p_ed, sizeof(ohci_ed_t)); } - hcd_devtree_info_t devtree_info; - hcd_devtree_get_info(dev_addr, &devtree_info); + tuh_bus_info_t bus_info; + hcd_bus_info_get(dev_addr, &bus_info); p_ed->dev_addr = dev_addr; p_ed->ep_number = ep_addr & 0x0F; p_ed->pid = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT); - p_ed->speed = devtree_info.speed; + p_ed->speed = bus_info.speed; p_ed->is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; p_ed->max_packet_size = ep_size; diff --git a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c index 225a44dcf..0e3d0d31a 100644 --- a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c +++ b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c @@ -114,9 +114,9 @@ void hcd_int_disable(uint8_t rhport) { //--------------------------------------------------------------------+ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *desc_ep) { - hcd_devtree_info_t dev_tree; - hcd_devtree_get_info(dev_addr, &dev_tree); - bool const need_pre = (dev_tree.hub_addr && dev_tree.speed == TUSB_SPEED_LOW); + tuh_bus_info_t bus_info; + hcd_bus_info_get(dev_addr, &bus_info); + bool const need_pre = (bus_info.hub_addr && bus_info.speed == TUSB_SPEED_LOW); uint8_t const pio_rhport = RHPORT_PIO(rhport); return pio_usb_host_endpoint_open(pio_rhport, dev_addr, (uint8_t const *) desc_ep, need_pre); diff --git a/src/portable/renesas/rusb2/hcd_rusb2.c b/src/portable/renesas/rusb2/hcd_rusb2.c index 3e4b36981..e6975287d 100644 --- a/src/portable/renesas/rusb2/hcd_rusb2.c +++ b/src/portable/renesas/rusb2/hcd_rusb2.c @@ -662,13 +662,13 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const if (0 == epn) { rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK; - hcd_devtree_info_t devtree; - hcd_devtree_get_info(dev_addr, &devtree); + tuh_bus_info_t bus_info; + hcd_bus_info_get(dev_addr, &bus_info); uint16_t volatile *devadd = (uint16_t volatile *)(uintptr_t) &rusb->DEVADD[0]; devadd += dev_addr; while (rusb->DCPCTR_b.PBUSY) {} rusb->DCPMAXP = (dev_addr << 12) | mps; - *devadd = (TUSB_SPEED_FULL == devtree.speed) ? RUSB2_DEVADD_USBSPD_FS : RUSB2_DEVADD_USBSPD_LS; + *devadd = (TUSB_SPEED_FULL == bus_info.speed) ? RUSB2_DEVADD_USBSPD_FS : RUSB2_DEVADD_USBSPD_LS; _hcd.ctl_mps[dev_addr] = mps; return true; } diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 53bc0b059..6fd343686 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -475,8 +475,8 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* dwc2_regs_t* dwc2 = DWC2_REG(rhport); const tusb_speed_t rh_speed = hprt_speed_get(dwc2); - hcd_devtree_info_t devtree_info; - hcd_devtree_get_info(dev_addr, &devtree_info); + tuh_bus_info_t bus_info; + hcd_bus_info_get(dev_addr, &bus_info); // find a free endpoint const uint8_t ep_id = edpt_alloc(); @@ -487,7 +487,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* hcchar_bm->ep_size = tu_edpt_packet_size(desc_ep); hcchar_bm->ep_num = tu_edpt_number(desc_ep->bEndpointAddress); hcchar_bm->ep_dir = tu_edpt_dir(desc_ep->bEndpointAddress); - hcchar_bm->low_speed_dev = (devtree_info.speed == TUSB_SPEED_LOW) ? 1 : 0; + hcchar_bm->low_speed_dev = (bus_info.speed == TUSB_SPEED_LOW) ? 1 : 0; hcchar_bm->ep_type = desc_ep->bmAttributes.xfer; // ep_type matches TUSB_XFER_* hcchar_bm->err_multi_count = 0; hcchar_bm->dev_addr = dev_addr; @@ -496,21 +496,21 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* hcchar_bm->enable = 1; dwc2_channel_split_t* hcsplt_bm = &edpt->hcsplt_bm; - hcsplt_bm->hub_port = devtree_info.hub_port; - hcsplt_bm->hub_addr = devtree_info.hub_addr; + hcsplt_bm->hub_port = bus_info.hub_port; + hcsplt_bm->hub_addr = bus_info.hub_addr; hcsplt_bm->xact_pos = 0; hcsplt_bm->split_compl = 0; - hcsplt_bm->split_en = (rh_speed == TUSB_SPEED_HIGH && devtree_info.speed != TUSB_SPEED_HIGH) ? 1 : 0; + hcsplt_bm->split_en = (rh_speed == TUSB_SPEED_HIGH && bus_info.speed != TUSB_SPEED_HIGH) ? 1 : 0; - edpt->speed = devtree_info.speed; + edpt->speed = bus_info.speed; edpt->next_pid = HCTSIZ_PID_DATA0; if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) { edpt->uframe_interval = 1 << (desc_ep->bInterval - 1); - if (devtree_info.speed == TUSB_SPEED_FULL) { + if (bus_info.speed == TUSB_SPEED_FULL) { edpt->uframe_interval <<= 3; } } else if (desc_ep->bmAttributes.xfer == TUSB_XFER_INTERRUPT) { - if (devtree_info.speed == TUSB_SPEED_HIGH) { + if (bus_info.speed == TUSB_SPEED_HIGH) { edpt->uframe_interval = 1 << (desc_ep->bInterval - 1); } else { edpt->uframe_interval = desc_ep->bInterval << 3; From a2da575793a14fdfc5137a02843af0fd8f8b772a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 23 Apr 2025 16:03:40 +0700 Subject: [PATCH 147/382] rename and expose tuh_bus_info_get() to application --- src/host/hcd.h | 10 ---------- src/host/usbh.c | 10 +++++----- src/host/usbh.h | 14 +++++++++++++- src/portable/chipidea/ci_hs/hcd_ci_hs.c | 1 + src/portable/ehci/ehci.c | 3 ++- src/portable/mentor/musb/hcd_musb.c | 5 +++-- src/portable/nxp/khci/hcd_khci.c | 1 + src/portable/nxp/lpc17_40/hcd_lpc17_40.c | 1 + src/portable/ohci/ohci.c | 3 ++- src/portable/raspberrypi/pio_usb/hcd_pio_usb.c | 2 +- src/portable/renesas/rusb2/hcd_rusb2.c | 3 ++- src/portable/synopsys/dwc2/dwc2_common.c | 1 + src/portable/synopsys/dwc2/hcd_dwc2.c | 3 ++- src/portable/template/hcd_template.c | 1 + 14 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/host/hcd.h b/src/host/hcd.h index 1f2704a10..d3551bf5b 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -90,13 +90,6 @@ typedef struct { }; } hcd_event_t; -typedef struct { - uint8_t rhport; - uint8_t hub_addr; - uint8_t hub_port; - uint8_t speed; -} tuh_bus_info_t; - //--------------------------------------------------------------------+ // Memory API //--------------------------------------------------------------------+ @@ -186,9 +179,6 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr); // USBH implemented API //--------------------------------------------------------------------+ -// Get device port information -extern bool hcd_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info); - // Called by HCD to notify stack extern void hcd_event_handler(hcd_event_t const* event, bool in_isr); diff --git a/src/host/usbh.c b/src/host/usbh.c index c063c97f9..0a208816c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -28,9 +28,9 @@ #if CFG_TUH_ENABLED -#include "host/hcd.h" +#include "hcd.h" #include "tusb.h" -#include "host/usbh_pvt.h" +#include "usbh_pvt.h" #include "hub.h" //--------------------------------------------------------------------+ @@ -342,7 +342,7 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid) { tusb_speed_t tuh_speed_get(uint8_t daddr) { tuh_bus_info_t bus_info; - hcd_bus_info_get(daddr, &bus_info); + tuh_bus_info_get(daddr, &bus_info); return bus_info.speed; } @@ -875,7 +875,7 @@ bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) { uint8_t usbh_get_rhport(uint8_t daddr) { tuh_bus_info_t bus_info; - hcd_bus_info_get(daddr, &bus_info); + tuh_bus_info_get(daddr, &bus_info); return bus_info.rhport; } @@ -1013,7 +1013,7 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) { // HCD Event Handler //--------------------------------------------------------------------+ -bool hcd_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info) { +bool tuh_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info) { usbh_device_t const* dev = get_device(daddr); if (dev) { *bus_info = dev->bus_info; diff --git a/src/host/usbh.h b/src/host/usbh.h index 4829a8183..063b20539 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -47,7 +47,6 @@ // forward declaration struct tuh_xfer_s; typedef struct tuh_xfer_s tuh_xfer_t; - typedef void (*tuh_xfer_cb_t)(tuh_xfer_t* xfer); // Note1: layout and order of this will be changed in near future @@ -80,6 +79,14 @@ typedef struct { tusb_desc_interface_t desc; } tuh_itf_info_t; +typedef struct { + uint8_t rhport; + uint8_t hub_addr; + uint8_t hub_port; + uint8_t speed; +} tuh_bus_info_t; + + // ConfigID for tuh_configure() enum { TUH_CFGID_INVALID = 0, @@ -177,6 +184,8 @@ extern void hcd_int_handler(uint8_t rhport, bool in_isr); #define _tuh_int_handler_arg0() TU_VERIFY_STATIC(false, "tuh_int_handler() must have 1 or 2 arguments") #define _tuh_int_handler_arg1(_rhport) hcd_int_handler(_rhport, true) #define _tuh_int_handler_arg2(_rhport, _in_isr) hcd_int_handler(_rhport, _in_isr) + +// 1st argument is rhport (mandatory), 2nd argument in_isr (optional) #define tuh_int_handler(...) TU_FUNC_OPTIONAL_ARG(_tuh_int_handler, __VA_ARGS__) // Check if roothub port is initialized and active as a host @@ -214,6 +223,9 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_ready(uint8_t daddr) { return tuh_mounted(daddr) && !tuh_suspended(daddr); } +// Get bus information of device +bool tuh_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info); + //--------------------------------------------------------------------+ // Transfer API //--------------------------------------------------------------------+ diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index c4c342a70..22eb22690 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -35,6 +35,7 @@ //--------------------------------------------------------------------+ #include "common/tusb_common.h" #include "host/hcd.h" +#include "host/usbh.h" #include "portable/ehci/ehci_api.h" #include "ci_hs_type.h" diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 141a2c026..da9f49d29 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -34,6 +34,7 @@ #include "osal/osal.h" #include "host/hcd.h" +#include "host/usbh.h" #include "ehci_api.h" #include "ehci.h" @@ -838,7 +839,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c } tuh_bus_info_t bus_info; - hcd_bus_info_get(dev_addr, &bus_info); + tuh_bus_info_get(dev_addr, &bus_info); uint8_t const xfer_type = ep_desc->bmAttributes.xfer; uint8_t const interval = ep_desc->bInterval; diff --git a/src/portable/mentor/musb/hcd_musb.c b/src/portable/mentor/musb/hcd_musb.c index 97ef46152..dcc023e0b 100644 --- a/src/portable/mentor/musb/hcd_musb.c +++ b/src/portable/mentor/musb/hcd_musb.c @@ -36,6 +36,7 @@ _Pragma("GCC diagnostic ignored \"-Waddress-of-packed-member\""); #endif #include "host/hcd.h" +#include "host/usbh.h" #include "musb_type.h" @@ -696,7 +697,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet _hcd.pipe0.remaining = 0; tuh_bus_info_t bus_info; - hcd_bus_info_get(dev_addr, &bus_info); + tuh_bus_info_get(dev_addr, &bus_info); switch (bus_info.speed) { default: return false; case TUSB_SPEED_LOW: USB0->TYPE0 = USB_TYPE0_SPEED_LOW; break; @@ -745,7 +746,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const uint8_t pipe_type = 0; tuh_bus_info_t bus_info; - hcd_bus_info_get(dev_addr, &bus_info); + tuh_bus_info_get(dev_addr, &bus_info); switch (bus_info.speed) { default: return false; case TUSB_SPEED_LOW: pipe_type |= USB_TXTYPE1_SPEED_LOW; break; diff --git a/src/portable/nxp/khci/hcd_khci.c b/src/portable/nxp/khci/hcd_khci.c index c3c901c5d..45732a866 100644 --- a/src/portable/nxp/khci/hcd_khci.c +++ b/src/portable/nxp/khci/hcd_khci.c @@ -36,6 +36,7 @@ #endif #include "host/hcd.h" +#include "host/usbh.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION diff --git a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c b/src/portable/nxp/lpc17_40/hcd_lpc17_40.c index 090d1ba69..fea3e2a66 100644 --- a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/hcd_lpc17_40.c @@ -31,6 +31,7 @@ #include "chip.h" #include "host/hcd.h" +#include "host/usbh.h" void hcd_int_enable(uint8_t rhport) { diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index 465b6731c..81091c9a7 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -38,6 +38,7 @@ #include "osal/osal.h" #include "host/hcd.h" +#include "host/usbh.h" #include "ohci.h" // TODO remove @@ -329,7 +330,7 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t } tuh_bus_info_t bus_info; - hcd_bus_info_get(dev_addr, &bus_info); + tuh_bus_info_get(dev_addr, &bus_info); p_ed->dev_addr = dev_addr; p_ed->ep_number = ep_addr & 0x0F; diff --git a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c index 0e3d0d31a..d59a2b4ee 100644 --- a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c +++ b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c @@ -115,7 +115,7 @@ void hcd_int_disable(uint8_t rhport) { bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *desc_ep) { tuh_bus_info_t bus_info; - hcd_bus_info_get(dev_addr, &bus_info); + tuh_bus_info_get(dev_addr, &bus_info); bool const need_pre = (bus_info.hub_addr && bus_info.speed == TUSB_SPEED_LOW); uint8_t const pio_rhport = RHPORT_PIO(rhport); diff --git a/src/portable/renesas/rusb2/hcd_rusb2.c b/src/portable/renesas/rusb2/hcd_rusb2.c index e6975287d..6f6d27d0e 100644 --- a/src/portable/renesas/rusb2/hcd_rusb2.c +++ b/src/portable/renesas/rusb2/hcd_rusb2.c @@ -30,6 +30,7 @@ #if CFG_TUH_ENABLED && defined(TUP_USBIP_RUSB2) #include "host/hcd.h" +#include "host/usbh.h" #include "rusb2_type.h" #if TU_CHECK_MCU(OPT_MCU_RX63X, OPT_MCU_RX65X, OPT_MCU_RX72N) @@ -663,7 +664,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const if (0 == epn) { rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK; tuh_bus_info_t bus_info; - hcd_bus_info_get(dev_addr, &bus_info); + tuh_bus_info_get(dev_addr, &bus_info); uint16_t volatile *devadd = (uint16_t volatile *)(uintptr_t) &rusb->DEVADD[0]; devadd += dev_addr; while (rusb->DCPCTR_b.PBUSY) {} diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index f6ed8fc98..e1e7d5c1a 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -36,6 +36,7 @@ #if CFG_TUH_ENABLED #include "host/hcd.h" +#include "host/usbh.h" #endif #include "dwc2_common.h" diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 6fd343686..7c29a03cf 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -36,6 +36,7 @@ #define DWC2_DEBUG 2 #include "host/hcd.h" +#include "host/usbh.h" #include "dwc2_common.h" // Max number of endpoints application can open, can be larger than DWC2_CHANNEL_COUNT_MAX @@ -476,7 +477,7 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t* const tusb_speed_t rh_speed = hprt_speed_get(dwc2); tuh_bus_info_t bus_info; - hcd_bus_info_get(dev_addr, &bus_info); + tuh_bus_info_get(dev_addr, &bus_info); // find a free endpoint const uint8_t ep_id = edpt_alloc(); diff --git a/src/portable/template/hcd_template.c b/src/portable/template/hcd_template.c index 22ea22e63..d2f304407 100644 --- a/src/portable/template/hcd_template.c +++ b/src/portable/template/hcd_template.c @@ -29,6 +29,7 @@ #if CFG_TUH_ENABLED && CFG_TUSB_MCU == OPT_MCU_NONE #include "host/hcd.h" +#include "host/usbh.h" //--------------------------------------------------------------------+ // Controller API From 9a1f690ec44dc7cc3e0dbb35e1db8ba89cd3de88 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 23 Apr 2025 16:50:58 +0700 Subject: [PATCH 148/382] move usbh ctrl_xfer into usbh_data --- src/host/usbh.c | 169 ++++++++++++++++++++++++------------------------ 1 file changed, 85 insertions(+), 84 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 0a208816c..9cf07213b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -263,7 +263,7 @@ static osal_queue_t _usbh_q; // Control transfers: since most controllers do not support multiple control transfers // on multiple devices concurrently and control transfers are not used much except for // enumeration, we will only execute control transfers one at a time. -static struct { +typedef struct { uint8_t* buffer; tuh_xfer_cb_t complete_cb; uintptr_t user_data; @@ -272,26 +272,25 @@ static struct { uint8_t daddr; volatile uint16_t actual_len; uint8_t failed_count; -} _ctrl_xfer; +} usbh_ctrl_xfer_info_t; typedef struct { - TUH_EPBUF_TYPE_DEF(tusb_control_request_t, request); - TUH_EPBUF_DEF(ctrl, CFG_TUH_ENUMERATION_BUFSIZE); -} usbh_epbuf_t; - -CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf; - -typedef struct { - uint8_t controller_id; // controller ID - uint8_t enumerating_daddr; // device address of the device being enumerated - - tuh_bus_info_t dev0_bus; // bus info for dev0 in enumeration + uint8_t controller_id; // controller ID + uint8_t enumerating_daddr; // device address of the device being enumerated + tuh_bus_info_t dev0_bus; // bus info for dev0 in enumeration + usbh_ctrl_xfer_info_t ctrl_xfer_info; // control transfer } usbh_data_t; static usbh_data_t _usbh_data = { .controller_id = TUSB_INDEX_INVALID_8, }; +typedef struct { + TUH_EPBUF_TYPE_DEF(tusb_control_request_t, request); + TUH_EPBUF_DEF(ctrl, CFG_TUH_ENUMERATION_BUFSIZE); +} usbh_epbuf_t; +CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf; + //------------- Helper Function -------------// TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) { TU_VERIFY(dev_addr > 0 && dev_addr <= TOTAL_DEVICES, NULL); @@ -299,7 +298,7 @@ TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) } static bool enum_new_device(hcd_event_t* event); -static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); +static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); @@ -388,9 +387,9 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Init host stack if not already if (!tuh_inited()) { + TU_LOG_INT_USBH(sizeof(usbh_data_t)); TU_LOG_INT_USBH(sizeof(usbh_device_t)); TU_LOG_INT_USBH(sizeof(hcd_event_t)); - TU_LOG_INT_USBH(sizeof(_ctrl_xfer)); TU_LOG_INT_USBH(sizeof(tuh_xfer_t)); TU_LOG_INT_USBH(sizeof(tu_fifo_t)); TU_LOG_INT_USBH(sizeof(tu_edpt_stream_t)); @@ -412,7 +411,6 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Device tu_memclr(_usbh_devices, sizeof(_usbh_devices)); - tu_memclr(&_ctrl_xfer, sizeof(_ctrl_xfer)); tu_memclr(&_usbh_data, sizeof(_usbh_data)); _usbh_data.controller_id = TUSB_INDEX_INVALID_8; @@ -451,7 +449,7 @@ bool tuh_deinit(uint8_t rhport) { _usbh_data.controller_id = TUSB_INDEX_INVALID_8; // "unplug" all devices on this rhport (hub_addr = 0, hub_port = 0) - process_removing_device(rhport, 0, 0); + process_removed_device(rhport, 0, 0); // deinit host stack if no controller is active if (!tuh_inited()) { @@ -545,7 +543,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { case HCD_EVENT_DEVICE_REMOVE: TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); - process_removing_device(event.rhport, event.connection.hub_addr, event.connection.hub_port); + process_removed_device(event.rhport, event.connection.hub_addr, event.connection.hub_port); #if CFG_TUH_HUB // TODO remove @@ -638,9 +636,9 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer) { } TU_ATTR_ALWAYS_INLINE static inline void _control_set_xfer_stage(uint8_t stage) { - if (_ctrl_xfer.stage != stage) { + if (_usbh_data.ctrl_xfer_info.stage != stage) { (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); - _ctrl_xfer.stage = stage; + _usbh_data.ctrl_xfer_info.stage = stage; (void) osal_mutex_unlock(_usbh_mutex); } } @@ -660,23 +658,22 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { const uint8_t daddr = xfer->daddr; TU_VERIFY(tuh_connected(daddr)); - // pre-check to help reducing mutex lock - TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE); + usbh_ctrl_xfer_info_t* ctrl_info = &_usbh_data.ctrl_xfer_info; + + TU_VERIFY(ctrl_info->stage == CONTROL_STAGE_IDLE); // pre-check to help reducing mutex lock (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); - - bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE); + bool const is_idle = (ctrl_info->stage == CONTROL_STAGE_IDLE); if (is_idle) { - _ctrl_xfer.stage = CONTROL_STAGE_SETUP; - _ctrl_xfer.daddr = daddr; - _ctrl_xfer.actual_len = 0; - _ctrl_xfer.failed_count = 0; + ctrl_info->stage = CONTROL_STAGE_SETUP; + ctrl_info->daddr = daddr; + ctrl_info->actual_len = 0; + ctrl_info->failed_count = 0; - _ctrl_xfer.buffer = xfer->buffer; - _ctrl_xfer.complete_cb = xfer->complete_cb; - _ctrl_xfer.user_data = xfer->user_data; + ctrl_info->buffer = xfer->buffer; + ctrl_info->complete_cb = xfer->complete_cb; + ctrl_info->user_data = xfer->user_data; _usbh_epbuf.request = (*xfer->setup); } - (void) osal_mutex_unlock(_usbh_mutex); TU_VERIFY(is_idle); @@ -693,8 +690,8 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { volatile xfer_result_t result = XFER_RESULT_INVALID; // use user_data to point to xfer_result_t - _ctrl_xfer.user_data = (uintptr_t) &result; - _ctrl_xfer.complete_cb = _control_blocking_complete_cb; + ctrl_info->user_data = (uintptr_t) &result; + ctrl_info->complete_cb = _control_blocking_complete_cb; TU_ASSERT(usbh_setup_send(daddr, (uint8_t const *) &_usbh_epbuf.request)); @@ -712,7 +709,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { *((xfer_result_t*) xfer->user_data) = result; } xfer->result = result; - xfer->actual_len = _ctrl_xfer.actual_len; + xfer->actual_len = ctrl_info->actual_len; } return true; @@ -720,6 +717,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { static void _control_xfer_complete(uint8_t daddr, xfer_result_t result) { TU_LOG_USBH("\r\n"); + usbh_ctrl_xfer_info_t* ctrl_info = &_usbh_data.ctrl_xfer_info; // duplicate xfer since user can execute control transfer within callback tusb_control_request_t const request = _usbh_epbuf.request; @@ -728,10 +726,10 @@ static void _control_xfer_complete(uint8_t daddr, xfer_result_t result) { .ep_addr = 0, .result = result, .setup = &request, - .actual_len = (uint32_t) _ctrl_xfer.actual_len, - .buffer = _ctrl_xfer.buffer, - .complete_cb = _ctrl_xfer.complete_cb, - .user_data = _ctrl_xfer.user_data + .actual_len = (uint32_t) ctrl_info->actual_len, + .buffer = ctrl_info->buffer, + .complete_cb = ctrl_info->complete_cb, + .user_data = ctrl_info->user_data }; _control_set_xfer_stage(CONTROL_STAGE_IDLE); @@ -746,6 +744,7 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t const uint8_t rhport = usbh_get_rhport(daddr); tusb_control_request_t const * request = &_usbh_epbuf.request; + usbh_ctrl_xfer_info_t* ctrl_info = &_usbh_data.ctrl_xfer_info; switch (result) { case XFER_RESULT_STALLED: @@ -755,12 +754,12 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t break; case XFER_RESULT_FAILED: - if (tuh_connected(daddr) && _ctrl_xfer.failed_count < USBH_CONTROL_RETRY_MAX) { - TU_LOG_USBH("[%u:%u] Control FAILED %u/%u, retrying\r\n", rhport, daddr, _ctrl_xfer.failed_count+1, USBH_CONTROL_RETRY_MAX); + if (tuh_connected(daddr) && ctrl_info->failed_count < USBH_CONTROL_RETRY_MAX) { + TU_LOG_USBH("[%u:%u] Control FAILED %u/%u, retrying\r\n", rhport, daddr, ctrl_info->failed_count+1, USBH_CONTROL_RETRY_MAX); (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); - _ctrl_xfer.stage = CONTROL_STAGE_SETUP; - _ctrl_xfer.failed_count++; - _ctrl_xfer.actual_len = 0; // reset actual_len + ctrl_info->stage = CONTROL_STAGE_SETUP; + ctrl_info->failed_count++; + ctrl_info->actual_len = 0; // reset actual_len (void) osal_mutex_unlock(_usbh_mutex); TU_ASSERT(usbh_setup_send(daddr, (uint8_t const *) request)); @@ -772,28 +771,29 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t break; case XFER_RESULT_SUCCESS: - switch(_ctrl_xfer.stage) { + switch(ctrl_info->stage) { case CONTROL_STAGE_SETUP: if (request->wLength) { // DATA stage: initial data toggle is always 1 _control_set_xfer_stage(CONTROL_STAGE_DATA); - TU_ASSERT(hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength)); + const uint8_t ep_data = tu_edpt_addr(0, request->bmRequestType_bit.direction); + TU_ASSERT(hcd_edpt_xfer(rhport, daddr, ep_data, ctrl_info->buffer, request->wLength)); return true; } - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; case CONTROL_STAGE_DATA: if (request->wLength) { TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, daddr); - TU_LOG_MEM_USBH(_ctrl_xfer.buffer, xferred_bytes, 2); + TU_LOG_MEM_USBH(ctrl_info->buffer, xferred_bytes, 2); } + ctrl_info->actual_len = (uint16_t) xferred_bytes; - _ctrl_xfer.actual_len = (uint16_t) xferred_bytes; - - // ACK stage: toggle is always 1 - _control_set_xfer_stage(CONTROL_STAGE_ACK); - TU_ASSERT( hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, 1 - request->bmRequestType_bit.direction), NULL, 0) ); - break; + // ACK stage: toggle is always 1 + _control_set_xfer_stage(CONTROL_STAGE_ACK); + const uint8_t ep_status = tu_edpt_addr(0, 1 - request->bmRequestType_bit.direction); + TU_ASSERT(hcd_edpt_xfer(rhport, daddr, ep_status, NULL, 0)); + break; case CONTROL_STAGE_ACK: { // Abort all pending transfers if SET_CONFIGURATION request @@ -842,16 +842,16 @@ bool tuh_edpt_xfer(tuh_xfer_t* xfer) { bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) { TU_LOG_USBH("[%u] Aborted transfer on EP %02X\r\n", daddr, ep_addr); - const uint8_t epnum = tu_edpt_number(ep_addr); const uint8_t dir = tu_edpt_dir(ep_addr); if (epnum == 0) { - // Also include dev0_bus for aborting enumerating + // Also include dev0 for aborting enumerating const uint8_t rhport = usbh_get_rhport(daddr); // control transfer: only 1 control at a time, check if we are aborting the current one - TU_VERIFY(daddr == _ctrl_xfer.daddr && _ctrl_xfer.stage != CONTROL_STAGE_IDLE); + const usbh_ctrl_xfer_info_t* ctrl_info = &_usbh_data.ctrl_xfer_info; + TU_VERIFY(daddr == ctrl_info->daddr && ctrl_info->stage != CONTROL_STAGE_IDLE); hcd_edpt_abort_xfer(rhport, daddr, ep_addr); _control_set_xfer_stage(CONTROL_STAGE_IDLE); // reset control transfer state to idle } else { @@ -859,9 +859,8 @@ bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) { TU_VERIFY(dev); TU_VERIFY(dev->ep_status[epnum][dir].busy); // non-control skip if not busy + // abort then mark as ready and release endpoint hcd_edpt_abort_xfer(dev->bus_info.rhport, daddr, ep_addr); - - // mark as ready and release endpoint if transfer is aborted dev->ep_status[epnum][dir].busy = false; tu_edpt_release(&dev->ep_status[epnum][dir], _usbh_mutex); } @@ -1252,16 +1251,18 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { } // a device unplugged from rhport:hub_addr:hub_port -static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { - // dev0_bus is unplugged - if ((_usbh_data.enumerating_daddr == 0) && (rhport == _usbh_data.dev0_bus.rhport) && - (hub_addr == _usbh_data.dev0_bus.hub_addr) && (hub_port == _usbh_data.dev0_bus.hub_port)) { - hcd_device_close(_usbh_data.dev0_bus.rhport, 0); - if (_ctrl_xfer.daddr == 0) { - _control_set_xfer_stage(CONTROL_STAGE_IDLE); +static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { + // if dev0 is unplugged while enumerating (not yet assigned an address) + if (_usbh_data.enumerating_daddr == 0) { + const tuh_bus_info_t* dev0_bus = &_usbh_data.dev0_bus; + if ((rhport == dev0_bus->rhport) && (hub_addr == dev0_bus->hub_addr) && (hub_port == dev0_bus->hub_port)) { + hcd_device_close(dev0_bus->rhport, 0); + if (_usbh_data.ctrl_xfer_info.daddr == 0) { + _control_set_xfer_stage(CONTROL_STAGE_IDLE); + } + _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; + return; } - _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; - return; } //------------- find the all devices (star-network) under port that is unplugged -------------// @@ -1298,8 +1299,8 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu hcd_device_close(rhport, daddr); clear_device(dev); - // abort on-going control xfer on this device if any - if (daddr == _ctrl_xfer.daddr) { + // abort ongoing control xfer on this device if any + if (daddr == _usbh_data.ctrl_xfer_info.daddr) { _control_set_xfer_stage(CONTROL_STAGE_IDLE); } @@ -1651,45 +1652,45 @@ static void process_enumeration(tuh_xfer_t* xfer) { } static bool enum_new_device(hcd_event_t* event) { - _usbh_data.dev0_bus.rhport = event->rhport; - _usbh_data.dev0_bus.hub_addr = event->connection.hub_addr; - _usbh_data.dev0_bus.hub_port = event->connection.hub_port; + tuh_bus_info_t* dev0_bus = &_usbh_data.dev0_bus; + dev0_bus->rhport = event->rhport; + dev0_bus->hub_addr = event->connection.hub_addr; + dev0_bus->hub_port = event->connection.hub_port; - if (_usbh_data.dev0_bus.hub_addr == 0) { + if (dev0_bus->hub_addr == 0) { // connected directly to roothub // wait until device connection is stable TODO non blocking tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); - // device unplugged while delaying - if (!hcd_port_connect_status(_usbh_data.dev0_bus.rhport)) { + if (!hcd_port_connect_status(dev0_bus->rhport)) { + TU_LOG_USBH("Device unplugged while debouncing\r\n"); enum_full_complete(); return true; } - hcd_port_reset(_usbh_data.dev0_bus.rhport); // reset device + hcd_port_reset(dev0_bus->rhport); // reset device // Since we are in middle of rhport reset, frame number is not available yet. - // need to depend on tusb_time_millis_api() + // need to depend on tusb_time_millis_api() TODO non blocking tusb_time_delay_ms_api(ENUM_RESET_DELAY_MS); - hcd_port_reset_end(_usbh_data.dev0_bus.rhport); + hcd_port_reset_end(dev0_bus->rhport); // device unplugged while delaying - if (!hcd_port_connect_status(_usbh_data.dev0_bus.rhport)) { + if (!hcd_port_connect_status(dev0_bus->rhport)) { enum_full_complete(); return true; } - _usbh_data.dev0_bus.speed = hcd_port_speed_get(_usbh_data.dev0_bus.rhport); - TU_LOG_USBH("%s Speed\r\n", tu_str_speed[_usbh_data.dev0.speed]); + dev0_bus->speed = hcd_port_speed_get(dev0_bus->rhport); + TU_LOG_USBH("%s Speed\r\n", tu_str_speed[dev0_bus->speed]); // fake transfer to kick-off the enumeration process tuh_xfer_t xfer; xfer.daddr = 0; xfer.result = XFER_RESULT_SUCCESS; xfer.user_data = ENUM_ADDR0_DEVICE_DESC; - process_enumeration(&xfer); } #if CFG_TUH_HUB @@ -1699,7 +1700,7 @@ static bool enum_new_device(hcd_event_t* event) { tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); // ENUM_HUB_GET_STATUS - TU_ASSERT(hub_port_get_status(_usbh_data.dev0_bus.hub_addr, _usbh_data.dev0_bus.hub_port, _usbh_epbuf.ctrl, + TU_ASSERT(hub_port_get_status(dev0_bus->hub_addr, dev0_bus->hub_port, _usbh_epbuf.ctrl, process_enumeration, ENUM_HUB_CLEAR_RESET_1)); } #endif // hub From 736b1d50bc4082e27b3dce0fcb95a90e202cd4d3 Mon Sep 17 00:00:00 2001 From: fenugrec Date: Wed, 23 Apr 2025 16:01:24 -0400 Subject: [PATCH 149/382] examples cmake: fix gcc flag -mcpu=cortex-m0 --- examples/build_system/cmake/cpu/cortex-m0.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/build_system/cmake/cpu/cortex-m0.cmake b/examples/build_system/cmake/cpu/cortex-m0.cmake index 62019d90d..f837c7eb8 100644 --- a/examples/build_system/cmake/cpu/cortex-m0.cmake +++ b/examples/build_system/cmake/cpu/cortex-m0.cmake @@ -1,7 +1,7 @@ if (TOOLCHAIN STREQUAL "gcc") set(TOOLCHAIN_COMMON_FLAGS -mthumb - -mcpu=cortex-m0plus + -mcpu=cortex-m0 -mfloat-abi=soft ) set(FREERTOS_PORT GCC_ARM_CM0 CACHE INTERNAL "") From 89f8d0cffbe259baed3163a22a42390c21ba1f53 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 24 Apr 2025 10:41:00 +0700 Subject: [PATCH 150/382] add tuh_address_set() API minor rename and move code around --- src/host/usbh.c | 160 ++++++++++++++++++++++++------------------------ src/host/usbh.h | 4 ++ 2 files changed, 83 insertions(+), 81 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 9cf07213b..f4a6e1697 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -105,13 +105,11 @@ typedef struct { // Device Descriptor uint8_t ep0_size; - - uint16_t vid; - uint16_t pid; - - uint8_t i_manufacturer; - uint8_t i_product; - uint8_t i_serial; + uint16_t idVendor; + uint16_t idProduct; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; uint8_t bNumConfigurations; // Configuration Descriptor @@ -331,10 +329,10 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid) { *vid = *pid = 0; usbh_device_t const *dev = get_device(dev_addr); - TU_VERIFY(dev && dev->addressed && dev->vid != 0); + TU_VERIFY(dev && dev->addressed && dev->idVendor != 0); - *vid = dev->vid; - *pid = dev->pid; + *vid = dev->idVendor; + *pid = dev->idProduct; return true; } @@ -1094,24 +1092,24 @@ bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { usbh_device_t const* dev = get_device(daddr); - TU_VERIFY(dev && dev->i_manufacturer); - return tuh_descriptor_get_string(daddr, dev->i_manufacturer, language_id, buffer, len, complete_cb, user_data); + TU_VERIFY(dev && dev->iManufacturer); + return tuh_descriptor_get_string(daddr, dev->iManufacturer, language_id, buffer, len, complete_cb, user_data); } // Get product string descriptor bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { usbh_device_t const* dev = get_device(daddr); - TU_VERIFY(dev && dev->i_product); - return tuh_descriptor_get_string(daddr, dev->i_product, language_id, buffer, len, complete_cb, user_data); + TU_VERIFY(dev && dev->iProduct); + return tuh_descriptor_get_string(daddr, dev->iProduct, language_id, buffer, len, complete_cb, user_data); } // Get serial string descriptor bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { usbh_device_t const* dev = get_device(daddr); - TU_VERIFY(dev && dev->i_serial); - return tuh_descriptor_get_string(daddr, dev->i_serial, language_id, buffer, len, complete_cb, user_data); + TU_VERIFY(dev && dev->iSerialNumber); + return tuh_descriptor_get_string(daddr, dev->iSerialNumber, language_id, buffer, len, complete_cb, user_data); } // Get HID report descriptor @@ -1142,6 +1140,33 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ return tuh_control_xfer(&xfer); } +bool tuh_address_set(uint8_t daddr, uint8_t new_addr, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + TU_LOG_USBH("Set Address = %d\r\n", new_addr); + const tusb_control_request_t request = { + .bmRequestType_bit = { + .recipient = TUSB_REQ_RCPT_DEVICE, + .type = TUSB_REQ_TYPE_STANDARD, + .direction = TUSB_DIR_OUT + }, + .bRequest = TUSB_REQ_SET_ADDRESS, + .wValue = tu_htole16(new_addr), + .wIndex = 0, + .wLength = 0 + }; + tuh_xfer_t xfer = { + .daddr = daddr, + .ep_addr = 0, + .setup = &request, + .buffer = NULL, + .complete_cb = complete_cb, + .user_data = user_data + }; + + TU_ASSERT(tuh_control_xfer(&xfer)); + return true; +} + bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_LOG_USBH("Set Configuration = %d\r\n", config_num); @@ -1373,7 +1398,7 @@ enum { ENUM_CONFIG_DRIVER }; -static bool enum_request_set_addr(tusb_desc_device_t const* desc_device); +static uint8_t enum_get_new_address(bool is_hub); static bool enum_parse_configuration_desc (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); static void enum_full_complete(void); @@ -1425,7 +1450,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { } _usbh_data.dev0_bus.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : - (port_status.status.low_speed) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; + (port_status.status.low_speed) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; // Acknowledge Port Reset Change if (port_status.change.reset) { @@ -1466,9 +1491,19 @@ static void process_enumeration(tuh_xfer_t* xfer) { break; } - case ENUM_SET_ADDR: - enum_request_set_addr((tusb_desc_device_t*) _usbh_epbuf.ctrl); + case ENUM_SET_ADDR: { + const tusb_desc_device_t *desc_device = (const tusb_desc_device_t *) _usbh_epbuf.ctrl; + const uint8_t new_addr = enum_get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); + TU_ASSERT(new_addr != 0,); + + usbh_device_t* new_dev = get_device(new_addr); + new_dev->bus_info = _usbh_data.dev0_bus; + new_dev->connected = 1; + new_dev->ep0_size = desc_device->bMaxPacketSize0; + + TU_ASSERT(tuh_address_set(0, new_addr, process_enumeration, ENUM_GET_DEVICE_DESC),); break; + } case ENUM_GET_DEVICE_DESC: { // Allow 2ms for address recovery time, Ref USB Spec 9.2.6.3 @@ -1495,11 +1530,11 @@ static void process_enumeration(tuh_xfer_t* xfer) { case ENUM_GET_STRING_LANGUAGE_ID_LEN: { // save the received device descriptor tusb_desc_device_t const *desc_device = (tusb_desc_device_t const *) _usbh_epbuf.ctrl; - dev->vid = desc_device->idVendor; - dev->pid = desc_device->idProduct; - dev->i_manufacturer = desc_device->iManufacturer; - dev->i_product = desc_device->iProduct; - dev->i_serial = desc_device->iSerialNumber; + dev->idVendor = desc_device->idVendor; + dev->idProduct = desc_device->idProduct; + dev->iManufacturer = desc_device->iManufacturer; + dev->iProduct = desc_device->iProduct; + dev->iSerialNumber = desc_device->iSerialNumber; dev->bNumConfigurations = desc_device->bNumConfigurations; tuh_enum_descriptor_device_cb(daddr, desc_device); // callback @@ -1520,8 +1555,8 @@ static void process_enumeration(tuh_xfer_t* xfer) { if (desc_langid->bLength >= 4) { langid = tu_le16toh(desc_langid->utf16le[0]); // previous request is langid } - if (dev->i_manufacturer != 0) { - tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, 2, + if (dev->iManufacturer != 0) { + tuh_descriptor_get_string(daddr, dev->iManufacturer, langid, _usbh_epbuf.ctrl, 2, process_enumeration, ENUM_GET_STRING_MANUFACTURER); break; }else { @@ -1530,10 +1565,10 @@ static void process_enumeration(tuh_xfer_t* xfer) { } case ENUM_GET_STRING_MANUFACTURER: { - if (dev->i_manufacturer != 0) { + if (dev->iManufacturer != 0) { langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request const uint8_t str_len = xfer->buffer[0]; - tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, str_len, + tuh_descriptor_get_string(daddr, dev->iManufacturer, langid, _usbh_epbuf.ctrl, str_len, process_enumeration, ENUM_GET_STRING_PRODUCT_LEN); break; } else { @@ -1542,11 +1577,11 @@ static void process_enumeration(tuh_xfer_t* xfer) { } case ENUM_GET_STRING_PRODUCT_LEN: - if (dev->i_product != 0) { + if (dev->iProduct != 0) { if (state == ENUM_GET_STRING_PRODUCT_LEN) { langid = tu_le16toh(xfer->setup->wIndex); // get langid from previous setup packet if not fall through } - tuh_descriptor_get_string(daddr, dev->i_product, langid, _usbh_epbuf.ctrl, 2, + tuh_descriptor_get_string(daddr, dev->iProduct, langid, _usbh_epbuf.ctrl, 2, process_enumeration, ENUM_GET_STRING_PRODUCT); break; } else { @@ -1554,10 +1589,10 @@ static void process_enumeration(tuh_xfer_t* xfer) { } case ENUM_GET_STRING_PRODUCT: { - if (dev->i_product != 0) { + if (dev->iProduct != 0) { langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request const uint8_t str_len = xfer->buffer[0]; - tuh_descriptor_get_string(daddr, dev->i_product, langid, _usbh_epbuf.ctrl, str_len, + tuh_descriptor_get_string(daddr, dev->iProduct, langid, _usbh_epbuf.ctrl, str_len, process_enumeration, ENUM_GET_STRING_SERIAL_LEN); break; } else { @@ -1566,11 +1601,11 @@ static void process_enumeration(tuh_xfer_t* xfer) { } case ENUM_GET_STRING_SERIAL_LEN: - if (dev->i_serial != 0) { + if (dev->iSerialNumber != 0) { if (state == ENUM_GET_STRING_SERIAL_LEN) { langid = tu_le16toh(xfer->setup->wIndex); // get langid from previous setup packet if not fall through } - tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, 2, + tuh_descriptor_get_string(daddr, dev->iSerialNumber, langid, _usbh_epbuf.ctrl, 2, process_enumeration, ENUM_GET_STRING_SERIAL); break; } else { @@ -1578,10 +1613,10 @@ static void process_enumeration(tuh_xfer_t* xfer) { } case ENUM_GET_STRING_SERIAL: { - if (dev->i_serial != 0) { + if (dev->iSerialNumber != 0) { langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request const uint8_t str_len = xfer->buffer[0]; - tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, str_len, + tuh_descriptor_get_string(daddr, dev->iSerialNumber, langid, _usbh_epbuf.ctrl, str_len, process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC); break; } else { @@ -1657,12 +1692,12 @@ static bool enum_new_device(hcd_event_t* event) { dev0_bus->hub_addr = event->connection.hub_addr; dev0_bus->hub_port = event->connection.hub_port; + // wait until device connection is stable TODO non blocking + tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); + if (dev0_bus->hub_addr == 0) { // connected directly to roothub - // wait until device connection is stable TODO non blocking - tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); - if (!hcd_port_connect_status(dev0_bus->rhport)) { TU_LOG_USBH("Device unplugged while debouncing\r\n"); enum_full_complete(); @@ -1696,10 +1731,6 @@ static bool enum_new_device(hcd_event_t* event) { #if CFG_TUH_HUB else { // connected via external hub - // wait until device connection is stable TODO non blocking - tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); - - // ENUM_HUB_GET_STATUS TU_ASSERT(hub_port_get_status(dev0_bus->hub_addr, dev0_bus->hub_port, _usbh_epbuf.ctrl, process_enumeration, ENUM_HUB_CLEAR_RESET_1)); } @@ -1708,7 +1739,7 @@ static bool enum_new_device(hcd_event_t* event) { return true; } -static uint8_t get_new_address(bool is_hub) { +static uint8_t enum_get_new_address(bool is_hub) { uint8_t start; uint8_t end; @@ -1721,47 +1752,14 @@ static uint8_t get_new_address(bool is_hub) { } for (uint8_t idx = start; idx < end; idx++) { - if (!_usbh_devices[idx].connected) return (idx+1); + if (!_usbh_devices[idx].connected) { + return (idx + 1); + } } return 0; // invalid address } -static bool enum_request_set_addr(tusb_desc_device_t const* desc_device) { - // Get new address - uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); - TU_ASSERT(new_addr != 0); - TU_LOG_USBH("Set Address = %d\r\n", new_addr); - - usbh_device_t* new_dev = get_device(new_addr); - new_dev->bus_info = _usbh_data.dev0_bus; - new_dev->connected = 1; - new_dev->ep0_size = desc_device->bMaxPacketSize0; - - tusb_control_request_t const request = { - .bmRequestType_bit = { - .recipient = TUSB_REQ_RCPT_DEVICE, - .type = TUSB_REQ_TYPE_STANDARD, - .direction = TUSB_DIR_OUT - }, - .bRequest = TUSB_REQ_SET_ADDRESS, - .wValue = tu_htole16(new_addr), - .wIndex = 0, - .wLength = 0 - }; - tuh_xfer_t xfer = { - .daddr = 0, - .ep_addr = 0, - .setup = &request, - .buffer = NULL, - .complete_cb = process_enumeration, - .user_data = ENUM_GET_DEVICE_DESC - }; - - TU_ASSERT(tuh_control_xfer(&xfer)); - return true; -} - static bool enum_parse_configuration_desc(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) { usbh_device_t* dev = get_device(dev_addr); uint16_t const total_len = tu_le16toh(desc_cfg->wTotalLength); diff --git a/src/host/usbh.h b/src/host/usbh.h index 063b20539..6f09f0c80 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -250,6 +250,10 @@ bool tuh_edpt_close(uint8_t daddr, uint8_t ep_addr); // Return true if a queued transfer is aborted, false if there is no transfer to abort bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr); +// Set Address (control transfer) +bool tuh_address_set(uint8_t daddr, uint8_t new_addr, + tuh_xfer_cb_t complete_cb, uintptr_t user_data); + // Set Configuration (control transfer) // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 // true on success, false if there is on-going control transfer or incorrect parameters From 0f784e8a072d30aaa6f4c6ef0a8f22a085ea2516 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 24 Apr 2025 17:59:45 +0700 Subject: [PATCH 151/382] refactor hub driver and move port reset on connection change to usbh. hub: add hub_port_get_status_local(), ignore resp in hub_port_get_status(pot != 0) usbh properly deboucning with hub/rootport accordingly to usb specs, also add 10ms of reset recovery --- src/host/hub.c | 230 ++++++++++++++++++++++++------------------------ src/host/hub.h | 8 +- src/host/usbh.c | 208 +++++++++++++++++++++---------------------- 3 files changed, 225 insertions(+), 221 deletions(-) diff --git a/src/host/hub.c b/src/host/hub.c index 61efa8ba5..c87289a14 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -57,9 +57,11 @@ typedef struct { TUH_EPBUF_DEF(ctrl_buf, CFG_TUH_HUB_BUFSIZE); } hub_epbuf_t; +static tuh_xfer_cb_t user_complete_cb = NULL; static hub_interface_t hub_itfs[CFG_TUH_HUB]; CFG_TUH_MEM_SECTION static hub_epbuf_t hub_epbufs[CFG_TUH_HUB]; + TU_ATTR_ALWAYS_INLINE static inline hub_interface_t* get_hub_itf(uint8_t daddr) { return &hub_itfs[daddr-1-CFG_TUH_DEVICE_MAX]; } @@ -142,10 +144,23 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, }; TU_LOG_DRV("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer(&xfer) ); + TU_ASSERT(tuh_control_xfer(&xfer)); return true; } +static void port_get_status_complete (tuh_xfer_t* xfer) { + if (xfer->result == XFER_RESULT_SUCCESS) { + hub_interface_t* p_hub = get_hub_itf(xfer->daddr); + p_hub->port_status = *((const hub_port_status_response_t *) (uintptr_t) xfer->buffer); + } + + xfer->complete_cb = user_complete_cb; + user_complete_cb = NULL; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } +} + bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request = { @@ -169,8 +184,26 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, .user_data = user_data }; + if (hub_port != 0) { + // intercept complete callback to save port status, ignore resp + hub_epbuf_t* p_epbuf = get_hub_epbuf(hub_addr); + xfer.complete_cb = port_get_status_complete; + xfer.buffer = p_epbuf->ctrl_buf; + user_complete_cb = complete_cb; + } else { + user_complete_cb = NULL; + } + TU_LOG_DRV("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); - TU_VERIFY( tuh_control_xfer(&xfer) ); + TU_VERIFY(tuh_control_xfer(&xfer)); + return true; +} + +bool hub_port_get_status_local(uint8_t hub_addr, uint8_t hub_port, hub_port_status_response_t* resp) { + (void) hub_port; + TU_VERIFY(hub_addr > CFG_TUH_DEVICE_MAX); + hub_interface_t* p_hub = get_hub_itf(hub_addr); + *resp = p_hub->port_status; return true; } @@ -238,10 +271,10 @@ bool hub_edpt_status_xfer(uint8_t daddr) { static void config_set_port_power (tuh_xfer_t* xfer); static void config_port_power_complete (tuh_xfer_t* xfer); -bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { - hub_interface_t* p_hub = get_hub_itf(dev_addr); +bool hub_set_config(uint8_t daddr, uint8_t itf_num) { + hub_interface_t* p_hub = get_hub_itf(daddr); TU_ASSERT(itf_num == p_hub->itf_num); - hub_epbuf_t* p_epbuf = get_hub_epbuf(dev_addr); + hub_epbuf_t* p_epbuf = get_hub_epbuf(daddr); // Get Hub Descriptor tusb_control_request_t const request = { @@ -257,7 +290,7 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { }; tuh_xfer_t xfer = { - .daddr = dev_addr, + .daddr = daddr, .ep_addr = 0, .setup = &request, .buffer = p_epbuf->ctrl_buf, @@ -312,11 +345,15 @@ static void config_port_power_complete (tuh_xfer_t* xfer) { //--------------------------------------------------------------------+ // Connection Changes //--------------------------------------------------------------------+ -static void get_status_complete (tuh_xfer_t* xfer); -static void port_get_status_complete (tuh_xfer_t* xfer); -static void port_clear_feature_complete_stub(tuh_xfer_t* xfer); -static void connection_clear_conn_change_complete (tuh_xfer_t* xfer); -static void connection_port_reset_complete (tuh_xfer_t* xfer); +enum { + STATE_IDLE = 0, + STATE_HUB_STATUS, + STATE_CLEAR_CHANGE, + STATE_CHECK_CONN, + STATE_COMPLETE +}; + +static void process_new_status(tuh_xfer_t* xfer); // callback as response of interrupt endpoint polling bool hub_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { @@ -337,12 +374,12 @@ bool hub_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t processed = false; } else if (tu_bit_test(status_change, 0)) { // Hub bit 0 is for the hub device events - processed = hub_get_status(daddr, p_epbuf->ctrl_buf, get_status_complete, 0); + processed = hub_get_status(daddr, p_epbuf->ctrl_buf, process_new_status, STATE_HUB_STATUS); } else { // Hub bits 1 to n are hub port events for (uint8_t port=1; port <= p_hub->bNbrPorts; port++) { if (tu_bit_test(status_change, port)) { - processed = hub_port_get_status(daddr, port, p_epbuf->ctrl_buf, port_get_status_complete, 0); + processed = hub_port_get_status(daddr, port, NULL, process_new_status, STATE_CLEAR_CHANGE); break; // after completely processed one port, we will re-queue the status poll and handle next one } } @@ -358,117 +395,84 @@ bool hub_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t return true; } -static void port_clear_feature_complete_stub(tuh_xfer_t* xfer) { - hub_edpt_status_xfer(xfer->daddr); -} - -static void get_status_complete(tuh_xfer_t *xfer) { - const uint8_t daddr = xfer->daddr; - - bool processed = false; // true if new status is processed - if (xfer->result == XFER_RESULT_SUCCESS) { - hub_status_response_t hub_status = *((const hub_status_response_t *) (uintptr_t) xfer->buffer); - - TU_LOG_DRV("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, hub_status.change.value); - - if (hub_status.change.local_power_source) { - TU_LOG_DRV(" Local Power Change\r\n"); - processed = hub_clear_feature(daddr, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, port_clear_feature_complete_stub, 0); - } else if (hub_status.change.over_current) { - TU_LOG_DRV(" Over Current\r\n"); - processed = hub_clear_feature(daddr, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0); - } - } - - if (!processed) { - TU_ASSERT(hub_edpt_status_xfer(daddr), ); - } -} - -static void port_get_status_complete(tuh_xfer_t *xfer) { - const uint8_t daddr = xfer->daddr; - bool processed = false; // true if new status is processed - - if (xfer->result == XFER_RESULT_SUCCESS) { - const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - hub_interface_t *p_hub = get_hub_itf(daddr); - p_hub->port_status = *((const hub_port_status_response_t *) (uintptr_t) xfer->buffer); - - // Clear port status change interrupts - if (p_hub->port_status.change.connection) { - // Connection change - // Port is powered and enabled - //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); - - // Acknowledge Port Connection Change - processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0); - } else if (p_hub->port_status.change.port_enable) { - processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_ENABLE_CHANGE, port_clear_feature_complete_stub, 0); - } else if (p_hub->port_status.change.suspend) { - processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_SUSPEND_CHANGE, port_clear_feature_complete_stub, 0); - } else if (p_hub->port_status.change.over_current) { - processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0); - } else if (p_hub->port_status.change.reset) { - processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, port_clear_feature_complete_stub, 0); - } - } - - if (!processed) { - TU_ASSERT(hub_edpt_status_xfer(daddr), ); - } -} - -static void connection_clear_conn_change_complete (tuh_xfer_t* xfer) { +static void process_new_status(tuh_xfer_t* xfer) { const uint8_t daddr = xfer->daddr; if (xfer->result != XFER_RESULT_SUCCESS) { - TU_ASSERT(hub_edpt_status_xfer(daddr), ); + TU_ASSERT(hub_edpt_status_xfer(daddr),); return; } + const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); hub_interface_t *p_hub = get_hub_itf(daddr); - const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + const uintptr_t state = xfer->user_data; + bool processed = false; // true if new status is processed - if (p_hub->port_status.status.connection) { - // Reset port if attach event - hub_port_reset(daddr, port_num, connection_port_reset_complete, 0); - } else { - // submit detach event - const hcd_event_t event = { - .rhport = usbh_get_rhport(daddr), - .event_id = HCD_EVENT_DEVICE_REMOVE, - .connection = { - .hub_addr = daddr, - .hub_port = port_num - } - }; - hcd_event_handler(&event, false); - } -} - -static void connection_port_reset_complete (tuh_xfer_t* xfer) { - const uint8_t daddr = xfer->daddr; - - if (xfer->result != XFER_RESULT_SUCCESS) { - // retry port reset if failed - if (!tuh_control_xfer(xfer)) { - TU_ASSERT(hub_edpt_status_xfer(daddr), ); // back to status poll if failed to queue request + switch (state) { + case STATE_HUB_STATUS: { + hub_status_response_t hub_status = *((const hub_status_response_t *) (uintptr_t) xfer->buffer); + TU_LOG_DRV("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, hub_status.change.value); + if (hub_status.change.local_power_source) { + TU_LOG_DRV(" Local Power Change\r\n"); + processed = hub_clear_feature(daddr, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, + process_new_status, STATE_COMPLETE); + } else if (hub_status.change.over_current) { + TU_LOG_DRV(" Over Current\r\n"); + processed = hub_clear_feature(daddr, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, + process_new_status, STATE_COMPLETE); + } + break; } - return; + + case STATE_CLEAR_CHANGE: + // Get port status complete --> clear change + if (p_hub->port_status.change.connection) { + // Connection change + // Port is powered and enabled + //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); + + // Acknowledge Port Connection Change + processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, + process_new_status, STATE_CHECK_CONN); + } else if (p_hub->port_status.change.port_enable) { + processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_ENABLE_CHANGE, + process_new_status, STATE_COMPLETE); + } else if (p_hub->port_status.change.suspend) { + processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_SUSPEND_CHANGE, + process_new_status, STATE_COMPLETE); + } else if (p_hub->port_status.change.over_current) { + processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, + process_new_status, STATE_COMPLETE); + } else if (p_hub->port_status.change.reset) { + processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, + process_new_status, STATE_COMPLETE); + } + break; + + case STATE_CHECK_CONN: { + const hcd_event_t event = { + .rhport = usbh_get_rhport(daddr), + .event_id = p_hub->port_status.status.connection ? HCD_EVENT_DEVICE_ATTACH : HCD_EVENT_DEVICE_REMOVE, + .connection = { + .hub_addr = daddr, + .hub_port = port_num + } + }; + hcd_event_handler(&event, false); + processed = true; // usbh queue status after handled this in (de)enumeration + break; + } + + case STATE_COMPLETE: + default: + processed = false; // complete this status, queue next status + break; + } - const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - - // submit attach event - hcd_event_t event = { - .rhport = usbh_get_rhport(daddr), - .event_id = HCD_EVENT_DEVICE_ATTACH, - .connection = { - .hub_addr = daddr, - .hub_port = port_num - } - }; - hcd_event_handler(&event, false); + if (!processed) { + TU_ASSERT(hub_edpt_status_xfer(daddr),); + } } #endif diff --git a/src/host/hub.h b/src/host/hub.h index e4e576661..3587f0ee3 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -170,9 +170,13 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get port status +// If hub_port != 0, resp is ignored. hub_port_get_status_local() can be used to retrieve the status bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void *resp, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +// Get port status from local cache. This does not send a request to the device +bool hub_port_get_status_local(uint8_t hub_addr, uint8_t hub_port, hub_port_status_response_t* resp); + // Get status from Interrupt endpoint bool hub_edpt_status_xfer(uint8_t daddr); @@ -188,7 +192,7 @@ bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_data); } -// Get Hub status +// Get Hub status (port = 0) TU_ATTR_ALWAYS_INLINE static inline bool hub_get_status(uint8_t hub_addr, void* resp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return hub_port_get_status(hub_addr, 0, resp, complete_cb, user_data); @@ -205,7 +209,7 @@ bool hub_clear_feature(uint8_t hub_addr, uint8_t feature, tuh_xfer_cb_t complete bool hub_init (void); bool hub_deinit (void); bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); +bool hub_set_config (uint8_t daddr, uint8_t itf_num); bool hub_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hub_close (uint8_t dev_addr); diff --git a/src/host/usbh.c b/src/host/usbh.c index f4a6e1697..94a1fa247 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -360,7 +360,6 @@ bool tuh_rhport_reset_bus(uint8_t rhport, bool active) { //--------------------------------------------------------------------+ // PUBLIC API (Parameter Verification is required) //--------------------------------------------------------------------+ - bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void *cfg_param) { return hcd_configure(rhport, cfg_id, cfg_param); } @@ -534,7 +533,6 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { } } else { TU_LOG1("[%u:] USBH Device Attach\r\n", event.rhport); - _usbh_data.enumerating_daddr = 0; enum_new_device(&event); } break; @@ -1022,9 +1020,11 @@ bool tuh_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info) { TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) { switch (event->event_id) { + case HCD_EVENT_DEVICE_ATTACH: + + break; + case HCD_EVENT_DEVICE_REMOVE: - // FIXME device remove from a hub need an HCD API for hcd to free up endpoint - // mark device as removing to prevent further xfer before the event is processed in usbh task break; default: break; @@ -1228,8 +1228,7 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt, TU_VERIFY(_async_func(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \ return (uint8_t) result -uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, - void* buffer, uint16_t len) { +uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get, daddr, type, index, buffer, len); } @@ -1237,33 +1236,27 @@ uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len _CONTROL_SYNC_API(tuh_descriptor_get_device, daddr, buffer, len); } -uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, - void* buffer, uint16_t len) { +uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_configuration, daddr, index, buffer, len); } -uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, - void* buffer, uint16_t len) { +uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_hid_report, daddr, itf_num, desc_type, index, buffer, len); } -uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, - void* buffer, uint16_t len) { +uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_string, daddr, index, language_id, buffer, len); } -uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, - void* buffer, uint16_t len) { +uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, daddr, language_id, buffer, len); } -uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, - void* buffer, uint16_t len) { +uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_product_string, daddr, language_id, buffer, len); } -uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, - void* buffer, uint16_t len) { +uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { _CONTROL_SYNC_API(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len); } @@ -1361,27 +1354,24 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub //--------------------------------------------------------------------+ // Enumeration Process -// is a lengthy process with a series of control transfer to configure -// newly attached device. +// is a lengthy process with a series of control transfer to configure newly attached device. // NOTE: due to the shared control buffer, we must complete enumerating // one device before enumerating another one. //--------------------------------------------------------------------+ - -enum { - ENUM_DEBOUNCING_DELAY_MS = 200, // when plug/unplug a device, physical connection can be bouncing and may - // generate a series of attach/detach event. This delay wait for stable connection - ENUM_RESET_DELAY_MS = 50, // USB specs: 10 to 50ms +enum { // USB 2.0 specs 7.1.7 for timing + ENUM_DEBOUNCING_DELAY_MS = 150, // T(ATTDB) minimum 100 ms for stable connection + ENUM_RESET_ROOT_DELAY_MS = 50, // T(DRSTr) minimum 50 ms for reset from root port + ENUM_RESET_HUB_DELAY_MS = 20, // T(DRST) 10-20 ms for hub reset + ENUM_RESET_RECOVERY_DELAY_MS = 10, // T(RSTRCY) minimum 10 ms for reset recovery }; enum { ENUM_IDLE, - ENUM_RESET_1, // 1st reset when attached - //ENUM_HUB_GET_STATUS_1, - ENUM_HUB_CLEAR_RESET_1, + ENUM_HUB_RERSET, + ENUM_HUB_GET_STATUS_AFTER_RESET, + ENUM_HUB_CLEAR_RESET, + ENUM_ADDR0_DEVICE_DESC, - ENUM_RESET_2, // 2nd reset before set address (not used) - ENUM_HUB_GET_STATUS_2, - ENUM_HUB_CLEAR_RESET_2, ENUM_SET_ADDR, ENUM_GET_DEVICE_DESC, ENUM_GET_STRING_LANGUAGE_ID_LEN, @@ -1401,6 +1391,63 @@ enum { static uint8_t enum_get_new_address(bool is_hub); static bool enum_parse_configuration_desc (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg); static void enum_full_complete(void); +static void process_enumeration(tuh_xfer_t* xfer); + +// start a new enumeration process +static bool enum_new_device(hcd_event_t* event) { + tuh_bus_info_t* dev0_bus = &_usbh_data.dev0_bus; + dev0_bus->rhport = event->rhport; + dev0_bus->hub_addr = event->connection.hub_addr; + dev0_bus->hub_port = event->connection.hub_port; + + _usbh_data.enumerating_daddr = 0; + + // wait until device connection is stable TODO non blocking + tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); + + if (dev0_bus->hub_addr == 0) { + // connected directly to roothub + // USB bus not active and frame number is not available yet. + // need to depend on tusb_time_millis_api() TODO non blocking + + if (!hcd_port_connect_status(dev0_bus->rhport)) { + TU_LOG_USBH("Device unplugged while debouncing\r\n"); + enum_full_complete(); + return true; + } + + // reset device + hcd_port_reset(dev0_bus->rhport); + tusb_time_delay_ms_api(ENUM_RESET_ROOT_DELAY_MS); + hcd_port_reset_end(dev0_bus->rhport); + + if (!hcd_port_connect_status(dev0_bus->rhport)) { + // device unplugged while delaying + enum_full_complete(); + return true; + } + + dev0_bus->speed = hcd_port_speed_get(dev0_bus->rhport); + TU_LOG_USBH("%s Speed\r\n", tu_str_speed[dev0_bus->speed]); + + // fake transfer to kick-off the enumeration process + tuh_xfer_t xfer; + xfer.daddr = 0; + xfer.result = XFER_RESULT_SUCCESS; + xfer.user_data = ENUM_ADDR0_DEVICE_DESC; + process_enumeration(&xfer); + } + #if CFG_TUH_HUB + else { + // connected via hub + TU_VERIFY(dev0_bus->hub_port != 0); + TU_ASSERT(hub_port_get_status(dev0_bus->hub_addr, dev0_bus->hub_port, NULL, + process_enumeration, ENUM_HUB_RERSET)); + } + #endif // hub + + return true; +} // process device enumeration static void process_enumeration(tuh_xfer_t* xfer) { @@ -1431,6 +1478,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { uint8_t const daddr = xfer->daddr; uintptr_t const state = xfer->user_data; usbh_device_t* dev = get_device(daddr); + tuh_bus_info_t* dev0_bus = &_usbh_data.dev0_bus; if (daddr > 0) { TU_ASSERT(dev,); } @@ -1438,53 +1486,54 @@ static void process_enumeration(tuh_xfer_t* xfer) { switch (state) { #if CFG_TUH_HUB - //case ENUM_HUB_GET_STATUS_1: break; - case ENUM_HUB_CLEAR_RESET_1: { + case ENUM_HUB_RERSET: { hub_port_status_response_t port_status; - memcpy(&port_status, _usbh_epbuf.ctrl, sizeof(hub_port_status_response_t)); + hub_port_get_status_local(dev0_bus->hub_addr, dev0_bus->hub_port, &port_status); if (!port_status.status.connection) { - // device unplugged while delaying, nothing else to do + TU_LOG_USBH("Device unplugged from hub while debouncing\r\n"); enum_full_complete(); return; } - _usbh_data.dev0_bus.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : - (port_status.status.low_speed) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; - - // Acknowledge Port Reset Change - if (port_status.change.reset) { - hub_port_clear_reset_change(_usbh_data.dev0_bus.hub_addr, _usbh_data.dev0_bus.hub_port, - process_enumeration, ENUM_ADDR0_DEVICE_DESC); - } + TU_ASSERT(hub_port_reset(dev0_bus->hub_addr, dev0_bus->hub_port, process_enumeration, ENUM_HUB_GET_STATUS_AFTER_RESET),); break; } - case ENUM_HUB_GET_STATUS_2: - tusb_time_delay_ms_api(ENUM_RESET_DELAY_MS); - TU_ASSERT(hub_port_get_status(_usbh_data.dev0_bus.hub_addr, _usbh_data.dev0_bus.hub_port, _usbh_epbuf.ctrl, - process_enumeration, ENUM_HUB_CLEAR_RESET_2),); + case ENUM_HUB_GET_STATUS_AFTER_RESET: { + tusb_time_delay_ms_api(ENUM_RESET_HUB_DELAY_MS); // wait for reset to take effect + + // get status to check for reset change + TU_ASSERT(hub_port_get_status(dev0_bus->hub_addr, dev0_bus->hub_port, NULL, process_enumeration, ENUM_HUB_CLEAR_RESET),); break; + } - case ENUM_HUB_CLEAR_RESET_2: { + case ENUM_HUB_CLEAR_RESET: { hub_port_status_response_t port_status; - memcpy(&port_status, _usbh_epbuf.ctrl, sizeof(hub_port_status_response_t)); + hub_port_get_status_local(dev0_bus->hub_addr, dev0_bus->hub_port, &port_status); + dev0_bus->speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : + (port_status.status.low_speed) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; - // Acknowledge Port Reset Change if Reset Successful if (port_status.change.reset) { - TU_ASSERT(hub_port_clear_reset_change(_usbh_data.dev0_bus.hub_addr, _usbh_data.dev0_bus.hub_port, - process_enumeration, ENUM_SET_ADDR),); + // Acknowledge Port Reset Change + TU_ASSERT(hub_port_clear_reset_change(dev0_bus->hub_addr, dev0_bus->hub_port, process_enumeration, ENUM_ADDR0_DEVICE_DESC),); + } else { + // maybe retry if reset change not set but we need timeout to prevent infinite loop + // TU_ASSERT(hub_port_get_status(dev0_bus->hub_addr, dev0_bus->hub_port, NULL, process_enumeration, ENUM_HUB_CLEAR_RESET),); } + break; } #endif case ENUM_ADDR0_DEVICE_DESC: { + tusb_time_delay_ms_api(ENUM_RESET_RECOVERY_DELAY_MS); // reset recovery + // TODO probably doesn't need to open/close each enumeration uint8_t const addr0 = 0; TU_ASSERT(usbh_edpt_control_open(addr0, 8),); - // Get first 8 bytes of device descriptor for Control Endpoint size + // Get first 8 bytes of device descriptor for control endpoint size TU_LOG_USBH("Get 8 byte of Device Descriptor\r\n"); TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_epbuf.ctrl, 8, process_enumeration, ENUM_SET_ADDR),); @@ -1686,59 +1735,6 @@ static void process_enumeration(tuh_xfer_t* xfer) { } } -static bool enum_new_device(hcd_event_t* event) { - tuh_bus_info_t* dev0_bus = &_usbh_data.dev0_bus; - dev0_bus->rhport = event->rhport; - dev0_bus->hub_addr = event->connection.hub_addr; - dev0_bus->hub_port = event->connection.hub_port; - - // wait until device connection is stable TODO non blocking - tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); - - if (dev0_bus->hub_addr == 0) { - // connected directly to roothub - - if (!hcd_port_connect_status(dev0_bus->rhport)) { - TU_LOG_USBH("Device unplugged while debouncing\r\n"); - enum_full_complete(); - return true; - } - - hcd_port_reset(dev0_bus->rhport); // reset device - - // Since we are in middle of rhport reset, frame number is not available yet. - // need to depend on tusb_time_millis_api() TODO non blocking - tusb_time_delay_ms_api(ENUM_RESET_DELAY_MS); - - hcd_port_reset_end(dev0_bus->rhport); - - // device unplugged while delaying - if (!hcd_port_connect_status(dev0_bus->rhport)) { - enum_full_complete(); - return true; - } - - dev0_bus->speed = hcd_port_speed_get(dev0_bus->rhport); - TU_LOG_USBH("%s Speed\r\n", tu_str_speed[dev0_bus->speed]); - - // fake transfer to kick-off the enumeration process - tuh_xfer_t xfer; - xfer.daddr = 0; - xfer.result = XFER_RESULT_SUCCESS; - xfer.user_data = ENUM_ADDR0_DEVICE_DESC; - process_enumeration(&xfer); - } -#if CFG_TUH_HUB - else { - // connected via external hub - TU_ASSERT(hub_port_get_status(dev0_bus->hub_addr, dev0_bus->hub_port, _usbh_epbuf.ctrl, - process_enumeration, ENUM_HUB_CLEAR_RESET_1)); - } -#endif // hub - - return true; -} - static uint8_t enum_get_new_address(bool is_hub) { uint8_t start; uint8_t end; From 093720f60b2b849f7129e532f8efef94c04d408b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 24 Apr 2025 18:08:00 +0700 Subject: [PATCH 152/382] fix build --- src/host/usbh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 94a1fa247..25942315b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1546,7 +1546,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { TU_ASSERT(new_addr != 0,); usbh_device_t* new_dev = get_device(new_addr); - new_dev->bus_info = _usbh_data.dev0_bus; + new_dev->bus_info = *dev0_bus; new_dev->connected = 1; new_dev->ep0_size = desc_device->bMaxPacketSize0; @@ -1564,7 +1564,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { new_dev->addressed = 1; _usbh_data.enumerating_daddr = new_addr; - hcd_device_close(_usbh_data.dev0_bus.rhport, 0); // close dev0_bus + hcd_device_close(dev0_bus->rhport, 0); // close dev0 TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->ep0_size),); // open new control endpoint From b5b7a4be60428193a773c1177456f138c21e48ad Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 24 Apr 2025 21:53:57 +0700 Subject: [PATCH 153/382] hub check status before get 1st device descriptor --- .idea/cmake.xml | 4 ++-- src/host/usbh.c | 23 +++++++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 7365e13a8..b8383a5ff 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -6,9 +6,9 @@ - - + + diff --git a/src/host/usbh.c b/src/host/usbh.c index 25942315b..8469aee83 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1370,6 +1370,7 @@ enum { ENUM_HUB_RERSET, ENUM_HUB_GET_STATUS_AFTER_RESET, ENUM_HUB_CLEAR_RESET, + ENUM_HUB_CLEAR_RESET_COMPLETE, ENUM_ADDR0_DEVICE_DESC, ENUM_SET_ADDR, @@ -1511,19 +1512,33 @@ static void process_enumeration(tuh_xfer_t* xfer) { case ENUM_HUB_CLEAR_RESET: { hub_port_status_response_t port_status; hub_port_get_status_local(dev0_bus->hub_addr, dev0_bus->hub_port, &port_status); - dev0_bus->speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : - (port_status.status.low_speed) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; if (port_status.change.reset) { // Acknowledge Port Reset Change - TU_ASSERT(hub_port_clear_reset_change(dev0_bus->hub_addr, dev0_bus->hub_port, process_enumeration, ENUM_ADDR0_DEVICE_DESC),); + TU_ASSERT(hub_port_clear_reset_change(dev0_bus->hub_addr, dev0_bus->hub_port, process_enumeration, ENUM_HUB_CLEAR_RESET_COMPLETE),); } else { // maybe retry if reset change not set but we need timeout to prevent infinite loop - // TU_ASSERT(hub_port_get_status(dev0_bus->hub_addr, dev0_bus->hub_port, NULL, process_enumeration, ENUM_HUB_CLEAR_RESET),); + // TU_ASSERT(hub_port_get_status(dev0_bus->hub_addr, dev0_bus->hub_port, NULL, process_enumeration, ENUM_HUB_CLEAR_RESET_COMPLETE),); } break; } + + case ENUM_HUB_CLEAR_RESET_COMPLETE: { + hub_port_status_response_t port_status; + hub_port_get_status_local(dev0_bus->hub_addr, dev0_bus->hub_port, &port_status); + + if (!port_status.status.connection) { + TU_LOG_USBH("Device unplugged from hub (not addressed yet)\r\n"); + enum_full_complete(); + return; + } + + dev0_bus->speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : + (port_status.status.low_speed) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; + + TU_ATTR_FALLTHROUGH; + } #endif case ENUM_ADDR0_DEVICE_DESC: { From 0937a2b2d3dbc0b5595c6ea3a6acc8a691f73941 Mon Sep 17 00:00:00 2001 From: Eli Hughes Date: Sat, 26 Apr 2025 13:04:39 -0400 Subject: [PATCH 154/382] using get-deps from tinyuf2 --- tools/get_deps.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/get_deps.py b/tools/get_deps.py index ba9dc23ce..d89c1b2b1 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -243,11 +243,13 @@ def get_a_dep(d): p.mkdir(parents=True) run_cmd(f"{git_cmd} init") run_cmd(f"{git_cmd} remote add origin {url}") + head = None + else: + # Check if commit is already fetched + result = run_cmd(f"{git_cmd} rev-parse HEAD") + head = result.stdout.decode("utf-8").splitlines()[0] + run_cmd(f"{git_cmd} reset --hard") - # Check if commit is already fetched - result = run_cmd(f"{git_cmd} rev-parse HEAD") - head = result.stdout.decode("utf-8").splitlines()[0] - run_cmd(f"{git_cmd} reset --hard") if commit != head: run_cmd(f"{git_cmd} fetch --depth 1 origin {commit}") run_cmd(f"{git_cmd} checkout FETCH_HEAD") From f392b4c91d725a02010cea46f94af3cb948b5136 Mon Sep 17 00:00:00 2001 From: Eli Hughes Date: Wed, 1 Jan 2025 13:22:48 -0500 Subject: [PATCH 155/382] Added initial support for FRDM-MCXA156 and fixed up a crash with MCXN947 I will be porting tinyuf2 to MCXA156 and N947 and need this work in place. This is the 1st step before bringing in support for other MCX devices. We had previous patched https://github.com/hathach/mcux-sdk.git' for MCX support as it was not pulically available I updated get_deps to point to the mcux-sdk version 2.16.10 from NXP. I repointed the entry in the get_deps script to use NXP MCU repo. The existing current code couldn't build as the MCUXpresso SDK was old. - For now, I put a copy of fsl_spc.c in the drivers folder for the mcx family. None of the ports could build with the version in the mcux github sdk. The sdk on github has version 2.4.0. The SDK package that can be downloaded with the SDK generator uses 2.4.2. All of the clock_config routines use versions of the datastructure from 2.4.2. For now, keeping an updated copy in hw/bsp/mcx/drivers so we can build against the latest mcuxpresso sdk and enable MCXA156. I'll file an issue on the nxp github. - Cleaned up the MCX family.c a little bit. the MCXA/N these chips don't have SCT so I removed the neopixel code. - fixed a clock init issue w/ N947 that was causing it to crash when initializing the uart. - I tested the cmake and make scripts on the A153,A156 and N947 using the CDC/MSC sample. All worked OK. - Patched get_deps so it will do a fetch/check on a new folder. Some of the deps were failing on a fresh clone of tinyusb - Fixed lpc51,54 and lpc55 make/cmake files to build with mcuxpresso sdk 2.16.10 The folder structure for flexcomm/uart changed a little bit - lpc55s59 libpower_hardabi.a no longer is included in mcuxpressosdk, (fsl_power.c is replacement). remove of libpower_hardabi.a from the linker config. LPC55 still works as expected. - Using tinyuf2 get deps --- README.rst | 4 +- hw/bsp/lpc51/family.cmake | 2 +- hw/bsp/lpc51/family.mk | 9 +- hw/bsp/lpc54/family.cmake | 3 +- hw/bsp/lpc54/family.mk | 3 +- hw/bsp/lpc55/family.cmake | 4 +- hw/bsp/lpc55/family.mk | 7 +- hw/bsp/mcx/boards/frdm_mcxa153/board.h | 4 +- hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c | 4 +- hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h | 2 +- hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c | 53 +- hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.h | 6 +- hw/bsp/mcx/boards/frdm_mcxa156/board.cmake | 21 + hw/bsp/mcx/boards/frdm_mcxa156/board.h | 69 + hw/bsp/mcx/boards/frdm_mcxa156/board.mk | 14 + hw/bsp/mcx/boards/frdm_mcxa156/clock_config.c | 482 ++++ hw/bsp/mcx/boards/frdm_mcxa156/clock_config.h | 170 ++ hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.c | 144 + hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.h | 51 + hw/bsp/mcx/boards/frdm_mcxn947/board.h | 13 +- hw/bsp/mcx/drivers/spc/fsl_spc.c | 1680 ++++++++++++ hw/bsp/mcx/drivers/spc/fsl_spc.h | 2433 +++++++++++++++++ hw/bsp/mcx/family.c | 30 +- hw/bsp/mcx/family.cmake | 28 +- hw/bsp/mcx/family.mk | 21 +- tools/get_deps.py | 14 +- 26 files changed, 5165 insertions(+), 106 deletions(-) create mode 100644 hw/bsp/mcx/boards/frdm_mcxa156/board.cmake create mode 100644 hw/bsp/mcx/boards/frdm_mcxa156/board.h create mode 100644 hw/bsp/mcx/boards/frdm_mcxa156/board.mk create mode 100644 hw/bsp/mcx/boards/frdm_mcxa156/clock_config.c create mode 100644 hw/bsp/mcx/boards/frdm_mcxa156/clock_config.h create mode 100644 hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.c create mode 100644 hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.h create mode 100644 hw/bsp/mcx/drivers/spc/fsl_spc.c create mode 100644 hw/bsp/mcx/drivers/spc/fsl_spc.h diff --git a/README.rst b/README.rst index efbfa354b..0d6b147d9 100644 --- a/README.rst +++ b/README.rst @@ -167,7 +167,9 @@ Supported CPUs | | +-------------------+--------+------+-----------+------------------------+-------------------+ | | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | | | +---------+-------------------+--------+------+-----------+------------------------+-------------------+ -| | MCX | N9, A15 | ✔ | | ✔ | ci_fs, ci_hs | | +| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs | | +| | +-------------------+--------+------+-----------+------------------------+-------------------+ +| | | A15 | ✔ | | | ci_fs | | +--------------+---------+-------------------+--------+------+-----------+------------------------+-------------------+ | Raspberry Pi | RP2040, RP2350 | ✔ | ✔ | ✖ | rp2040, pio_usb | | +--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+ diff --git a/hw/bsp/lpc51/family.cmake b/hw/bsp/lpc51/family.cmake index 2146c29f7..09d97d256 100644 --- a/hw/bsp/lpc51/family.cmake +++ b/hw/bsp/lpc51/family.cmake @@ -36,7 +36,7 @@ function(add_board_target BOARD_TARGET) # driver ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c ${SDK_DIR}/drivers/flexcomm/fsl_flexcomm.c - ${SDK_DIR}/drivers/flexcomm/fsl_usart.c + ${SDK_DIR}/drivers/flexcomm/usart/fsl_usart.c # mcu ${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_VARIANT}.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c diff --git a/hw/bsp/lpc51/family.mk b/hw/bsp/lpc51/family.mk index b41b5438e..f37360a71 100644 --- a/hw/bsp/lpc51/family.mk +++ b/hw/bsp/lpc51/family.mk @@ -28,18 +28,19 @@ SRC_C += \ $(MCU_DIR)/drivers/fsl_reset.c \ $(SDK_DIR)/drivers/lpc_gpio/fsl_gpio.c \ $(SDK_DIR)/drivers/flexcomm/fsl_flexcomm.c \ - $(SDK_DIR)/drivers/flexcomm/fsl_usart.c + $(SDK_DIR)/drivers/flexcomm/usart/fsl_usart.c INC += \ - $(TOP)/$(BOARD_PATH) \ - $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(MCU_DIR) \ $(TOP)/$(MCU_DIR)/drivers \ $(TOP)/$(SDK_DIR)/drivers/common \ $(TOP)/$(SDK_DIR)/drivers/flexcomm \ + $(TOP)/$(SDK_DIR)/drivers/flexcomm/usart \ $(TOP)/$(SDK_DIR)/drivers/lpc_iocon \ $(TOP)/$(SDK_DIR)/drivers/lpc_gpio - + SRC_S += $(MCU_DIR)/gcc/startup_$(MCU).S LIBS += $(TOP)/$(MCU_DIR)/gcc/libpower.a diff --git a/hw/bsp/lpc54/family.cmake b/hw/bsp/lpc54/family.cmake index 90497b9fb..66320870a 100644 --- a/hw/bsp/lpc54/family.cmake +++ b/hw/bsp/lpc54/family.cmake @@ -44,7 +44,7 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c ${SDK_DIR}/drivers/common/fsl_common_arm.c ${SDK_DIR}/drivers/flexcomm/fsl_flexcomm.c - ${SDK_DIR}/drivers/flexcomm/fsl_usart.c + ${SDK_DIR}/drivers/flexcomm/usart/fsl_usart.c # mcu ${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_CORE}.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c @@ -56,6 +56,7 @@ function(add_board_target BOARD_TARGET) # driver ${SDK_DIR}/drivers/common ${SDK_DIR}/drivers/flexcomm + ${SDK_DIR}/drivers/flexcomm/usart ${SDK_DIR}/drivers/lpc_iocon ${SDK_DIR}/drivers/lpc_gpio ${SDK_DIR}/drivers/lpuart diff --git a/hw/bsp/lpc54/family.mk b/hw/bsp/lpc54/family.mk index ea4c9c39c..8dc70f621 100644 --- a/hw/bsp/lpc54/family.mk +++ b/hw/bsp/lpc54/family.mk @@ -36,7 +36,7 @@ SRC_C += \ $(MCU_DIR)/drivers/fsl_reset.c \ $(SDK_DIR)/drivers/lpc_gpio/fsl_gpio.c \ $(SDK_DIR)/drivers/flexcomm/fsl_flexcomm.c \ - $(SDK_DIR)/drivers/flexcomm/fsl_usart.c \ + $(SDK_DIR)/drivers/flexcomm/usart/fsl_usart.c \ $(SDK_DIR)/drivers/common/fsl_common_arm.c INC += \ @@ -46,6 +46,7 @@ INC += \ $(TOP)/$(MCU_DIR)/drivers \ $(TOP)/$(SDK_DIR)/drivers/common \ $(TOP)/$(SDK_DIR)/drivers/flexcomm \ + $(TOP)/$(SDK_DIR)/drivers/flexcomm/usart \ $(TOP)/$(SDK_DIR)/drivers/lpc_iocon \ $(TOP)/$(SDK_DIR)/drivers/lpc_gpio diff --git a/hw/bsp/lpc55/family.cmake b/hw/bsp/lpc55/family.cmake index cd1eb5f78..a89548635 100644 --- a/hw/bsp/lpc55/family.cmake +++ b/hw/bsp/lpc55/family.cmake @@ -44,7 +44,7 @@ function(add_board_target BOARD_TARGET) ${SDK_DIR}/drivers/lpc_gpio/fsl_gpio.c ${SDK_DIR}/drivers/common/fsl_common_arm.c ${SDK_DIR}/drivers/flexcomm/fsl_flexcomm.c - ${SDK_DIR}/drivers/flexcomm/fsl_usart.c + ${SDK_DIR}/drivers/flexcomm/usart/fsl_usart.c # mcu ${SDK_DIR}/devices/${MCU_VARIANT}/system_${MCU_CORE}.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c @@ -56,9 +56,9 @@ function(add_board_target BOARD_TARGET) # driver ${SDK_DIR}/drivers/common ${SDK_DIR}/drivers/flexcomm + ${SDK_DIR}/drivers/flexcomm/usart ${SDK_DIR}/drivers/lpc_iocon ${SDK_DIR}/drivers/lpc_gpio - ${SDK_DIR}/drivers/lpuart ${SDK_DIR}/drivers/sctimer # mcu ${SDK_DIR}/devices/${MCU_VARIANT} diff --git a/hw/bsp/lpc55/family.mk b/hw/bsp/lpc55/family.mk index d82e85904..85b9a2cc9 100644 --- a/hw/bsp/lpc55/family.mk +++ b/hw/bsp/lpc55/family.mk @@ -45,7 +45,7 @@ SRC_C += \ $(SDK_DIR)/drivers/lpc_gpio/fsl_gpio.c \ $(SDK_DIR)/drivers/common/fsl_common_arm.c \ $(SDK_DIR)/drivers/flexcomm/fsl_flexcomm.c \ - $(SDK_DIR)/drivers/flexcomm/fsl_usart.c \ + $(SDK_DIR)/drivers/flexcomm/usart/fsl_usart.c \ lib/sct_neopixel/sct_neopixel.c INC += \ @@ -55,11 +55,12 @@ INC += \ $(TOP)/$(MCU_DIR) \ $(TOP)/$(MCU_DIR)/drivers \ $(TOP)/$(SDK_DIR)/drivers/common \ - $(TOP)/$(SDK_DIR)/drivers/flexcomm \ + $(TOP)/$(SDK_DIR)/drivers/flexcomm/usart \ + $(TOP)/$(SDK_DIR)/drivers/flexcomm/ \ $(TOP)/$(SDK_DIR)/drivers/lpc_iocon \ $(TOP)/$(SDK_DIR)/drivers/lpc_gpio \ $(TOP)/$(SDK_DIR)/drivers/sctimer SRC_S += $(MCU_DIR)/gcc/startup_$(MCU_CORE).S -LIBS += $(TOP)/$(MCU_DIR)/gcc/libpower_hardabi.a + diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/board.h b/hw/bsp/mcx/boards/frdm_mcxa153/board.h index fb1290088..86f987de9 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/board.h +++ b/hw/bsp/mcx/boards/frdm_mcxa153/board.h @@ -39,10 +39,10 @@ extern "C" { // LED #define LED_GPIO GPIO3 #define LED_CLK kCLOCK_GateGPIO3 -#define LED_PIN 12 // red +#define LED_PIN 12 //red #define LED_STATE_ON 0 -// ISP button (Dummy, use unused pin +// ISP button #define BUTTON_GPIO GPIO3 #define BUTTON_CLK kCLOCK_GateGPIO3 #define BUTTON_PIN 29 //sw2 diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c b/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c index f16bc51f6..5a132dc67 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c +++ b/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.c @@ -45,14 +45,13 @@ processor_version: 0.13.0 * Variables ******************************************************************************/ /* System clock frequency. */ -//uint32_t SystemCoreClock; +//extern uint32_t SystemCoreClock; /******************************************************************************* ************************ BOARD_InitBootClocks function ************************ ******************************************************************************/ void BOARD_InitBootClocks(void) { - BOARD_BootClockFRO96M(); } /******************************************************************************* @@ -386,7 +385,6 @@ void BOARD_BootClockFRO64M(void) /* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* !!Configuration name: BOARD_BootClockFRO96M -called_from_default_init: true outputs: - {id: CLK_1M_clock.outFreq, value: 1 MHz} - {id: CLK_48M_clock.outFreq, value: 48 MHz} diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h b/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h index aae811052..079d0d312 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h +++ b/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h @@ -4,7 +4,7 @@ * * SPDX-License-Identifier: BSD-3-Clause */ - + /*********************************************************************************************************************** * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c b/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c index cc8f56e63..fce756e72 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c +++ b/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c @@ -4,7 +4,6 @@ * * SPDX-License-Identifier: BSD-3-Clause */ - /*********************************************************************************************************************** * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. @@ -18,16 +17,13 @@ product: Pins v14.0 processor: MCXA153 package_id: MCXA153VLH mcu_data: ksdk2_0 -processor_version: 0.14.3 -pin_labels: -- {pin_num: '38', pin_signal: P3_12/LPUART2_RTS_B/CT1_MAT2/PWM0_X0, label: LED_RED, identifier: LED_RED} +processor_version: 0.14.4 * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** */ /* clang-format on */ #include "fsl_common.h" #include "fsl_port.h" -#include "fsl_gpio.h" #include "pin_mux.h" /* FUNCTION ************************************************************************************************************ @@ -47,8 +43,10 @@ void BOARD_InitBootPins(void) BOARD_InitPins: - options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} - pin_list: - - {pin_num: '38', peripheral: GPIO3, signal: 'GPIO, 12', pin_signal: P3_12/LPUART2_RTS_B/CT1_MAT2/PWM0_X0, direction: OUTPUT, gpio_init_state: 'false', slew_rate: fast, - open_drain: disable, drive_strength: low, pull_select: down, pull_enable: disable, input_buffer: enable, invert_input: normal} + - {pin_num: '51', peripheral: LPUART0, signal: RX, pin_signal: P0_2/TDO/SWO/LPUART0_RXD/LPSPI0_SCK/CT0_MAT0/UTICK_CAP0/I3C0_PUR, slew_rate: fast, open_drain: disable, + drive_strength: low, pull_select: up, pull_enable: enable, input_buffer: enable, invert_input: normal} + - {pin_num: '52', peripheral: LPUART0, signal: TX, pin_signal: P0_3/TDI/LPUART0_TXD/LPSPI0_SDO/CT0_MAT1/UTICK_CAP1/CMP0_OUT/CMP1_IN1, slew_rate: fast, open_drain: disable, + drive_strength: low, pull_select: up, pull_enable: enable, input_buffer: enable, invert_input: normal} * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** */ /* clang-format on */ @@ -61,15 +59,6 @@ BOARD_InitPins: * END ****************************************************************************************************************/ void BOARD_InitPins(void) { - RESET_PeripheralReset(kLPUART0_RST_SHIFT_RSTn); - RESET_PeripheralReset(kPORT0_RST_SHIFT_RSTn); - CLOCK_SetClockDiv(kCLOCK_DivLPUART0, 1u); - CLOCK_AttachClk(kFRO12M_to_LPUART0); - - /* write to PORT0: Peripheral clock is enabled */ - CLOCK_EnableClock(kCLOCK_GatePORT0); - - /* Write to GPIO3: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GateGPIO3); /* Write to PORT3: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GatePORT3); @@ -78,30 +67,13 @@ void BOARD_InitPins(void) /* PORT3 peripheral is released from reset */ RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); - const port_pin_config_t port3_12_pin38_config = {/* Internal pull-up/down resistor is disabled */ - kPORT_PullDisable, - /* Low internal pull resistor value is selected. */ - kPORT_LowPullResistor, - /* Fast slew rate is configured */ - kPORT_FastSlewRate, - /* Passive input filter is disabled */ - kPORT_PassiveFilterDisable, - /* Open drain output is disabled */ - kPORT_OpenDrainDisable, - /* Low drive strength is configured */ - kPORT_LowDriveStrength, - /* Normal drive strength is configured */ - kPORT_NormalDriveStrength, - /* Pin is configured as P3_12 */ - kPORT_MuxAlt0, - /* Digital input enabled */ - kPORT_InputBufferEnable, - /* Digital input is not inverted */ - kPORT_InputNormal, - /* Pin Control Register fields [15:0] are not locked */ - kPORT_UnlockRegister}; - /* PORT3_12 (pin 38) is configured as P3_12 */ - PORT_SetPinConfig(PORT3, 12U, &port3_12_pin38_config); + + /* Write to PORT0: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT0); + /* LPUART0 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kLPUART0_RST_SHIFT_RSTn); + /* PORT0 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); const port_pin_config_t port0_2_pin51_config = {/* Internal pull-up resistor is enabled */ kPORT_PullUp, @@ -152,7 +124,6 @@ void BOARD_InitPins(void) kPORT_UnlockRegister}; /* PORT0_3 (pin 52) is configured as LPUART0_TXD */ PORT_SetPinConfig(PORT0, 3U, &port0_3_pin52_config); - } /*********************************************************************************************************************** * EOF diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.h b/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.h index 06b6fdee9..2c0e617a5 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.h +++ b/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.h @@ -1,9 +1,13 @@ /* - * Copyright 2022 NXP + * Copyright 2023 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ #ifndef _PIN_MUX_H_ #define _PIN_MUX_H_ diff --git a/hw/bsp/mcx/boards/frdm_mcxa156/board.cmake b/hw/bsp/mcx/boards/frdm_mcxa156/board.cmake new file mode 100644 index 000000000..a6aa6c2e4 --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa156/board.cmake @@ -0,0 +1,21 @@ +set(MCU_VARIANT MCXA156) +set(MCU_CORE MCXA156) + +set(JLINK_DEVICE MCXA156_M33) +set(PYOCD_TARGET MCXA156) +set(NXPLINK_DEVICE MCXA156:MCXA156) + +set(PORT 0) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + CPU_MCXA156VLH + BOARD_TUD_RHPORT=0 + BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED + CFG_EXAMPLE_VIDEO_READONLY + ) + target_sources(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/clock_config.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/pin_mux.c + ) +endfunction() diff --git a/hw/bsp/mcx/boards/frdm_mcxa156/board.h b/hw/bsp/mcx/boards/frdm_mcxa156/board.h new file mode 100644 index 000000000..6c19797c6 --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa156/board.h @@ -0,0 +1,69 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: Freedom MCXA156 + url: https://www.nxp.com/design/design-center/development-boards-and-designs/FRDM-MCXA156 +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// LED +#define LED_GPIO GPIO3 +#define LED_CLK kCLOCK_GateGPIO3 +#define LED_PIN 12 // red +#define LED_STATE_ON 0 + +// ISP button +#define BUTTON_GPIO GPIO0 +#define BUTTON_CLK kCLOCK_GateGPIO0 +#define BUTTON_PIN 6 //SW3 +#define BUTTON_STATE_ACTIVE 0 + +// UART +#define UART_DEV LPUART0 + +static inline void board_uart_init_clock(void) { + /* attach 12 MHz clock to LPUART0 (debug console) */ + CLOCK_SetClockDiv(kCLOCK_DivLPUART0, 1u); + CLOCK_AttachClk(kFRO12M_to_LPUART0); + + RESET_PeripheralReset(kLPUART0_RST_SHIFT_RSTn); +} + +// XTAL +#define XTAL0_CLK_HZ (24 * 1000 * 1000U) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/mcx/boards/frdm_mcxa156/board.mk b/hw/bsp/mcx/boards/frdm_mcxa156/board.mk new file mode 100644 index 000000000..d4a59b32a --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa156/board.mk @@ -0,0 +1,14 @@ +MCU_VARIANT = MCXA156 +MCU_CORE = MCXA156 +PORT = 0 + +CPU_CORE = cortex-m33-nodsp-nofp +CFLAGS += \ + -DCPU_MCXA156VLH \ + -DCFG_TUSB_MCU=OPT_MCU_MCXA15 \ + +JLINK_DEVICE = MCXA156 +PYOCD_TARGET = MCXA156 + +# flash using pyocd +flash: flash-jlink diff --git a/hw/bsp/mcx/boards/frdm_mcxa156/clock_config.c b/hw/bsp/mcx/boards/frdm_mcxa156/clock_config.c new file mode 100644 index 000000000..f549af243 --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa156/clock_config.c @@ -0,0 +1,482 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ +/* + * How to setup clock using clock driver functions: + * + * 1. Setup clock sources. + * + * 2. Set up wait states of the flash. + * + * 3. Set up all dividers. + * + * 4. Set up all selectors to provide selected clocks. + * + */ + +/* clang-format off */ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!GlobalInfo +product: Clocks v13.0 +processor: MCXA156 +package_id: MCXA156VLL +mcu_data: ksdk2_0 +processor_version: 0.15.0 + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ +/* clang-format on */ + +#include "fsl_clock.h" +#include "clock_config.h" +#include "fsl_spc.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ +/* System clock frequency. */ +//extern uint32_t SystemCoreClock; + +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ +void BOARD_InitBootClocks(void) +{ + BOARD_BootClockFRO96M(); +} + +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO12M ********************** + ******************************************************************************/ +/* clang-format off */ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!Configuration +name: BOARD_BootClockFRO12M +outputs: +- {id: CLK_1M_clock.outFreq, value: 1 MHz} +- {id: CPU_clock.outFreq, value: 12 MHz} +- {id: FRO_12M_clock.outFreq, value: 12 MHz} +- {id: MAIN_clock.outFreq, value: 12 MHz} +- {id: Slow_clock.outFreq, value: 3 MHz} +- {id: System_clock.outFreq, value: 12 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +settings: +- {id: SCGMode, value: SIRC} +- {id: FRO_HF_PERIPHERALS_EN_CFG, value: Disabled} +- {id: MRCC.FREQMEREFCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FREQMETARGETCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.OSTIMERCLKSEL.sel, value: VBAT.CLK16K_1} +- {id: SCG.SCSSEL.sel, value: SCG.SIRC} +- {id: SCG_FIRCCSR_FIRCEN_CFG, value: Disabled} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ +/* clang-format on */ + +/******************************************************************************* + * Variables for BOARD_BootClockFRO12M configuration + ******************************************************************************/ +/******************************************************************************* + * Code for BOARD_BootClockFRO12M configuration + ******************************************************************************/ +void BOARD_BootClockFRO12M(void) +{ + uint32_t coreFreq; + spc_active_mode_core_ldo_option_t ldoOption; + spc_sram_voltage_config_t sramOption; + + /* Get the CPU Core frequency */ + coreFreq = CLOCK_GetCoreSysClkFreq(); + + /* The flow of increasing voltage and frequency */ + if (coreFreq <= BOARD_BOOTCLOCKFRO12M_CORE_CLOCK) { + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_MidDriveVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x0U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P0V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + } + + CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */ + + CLOCK_AttachClk(kFRO12M_to_MAIN_CLK); /* !< Switch MAIN_CLK to FRO12M */ + + /* The flow of decreasing voltage and frequency */ + if (coreFreq > BOARD_BOOTCLOCKFRO12M_CORE_CLOCK) { + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x0U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P0V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_MidDriveVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + } + + /*!< Set up clock selectors - Attach clocks to the peripheries */ + + /*!< Set up dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ + + /* Set SystemCoreClock variable */ + SystemCoreClock = BOARD_BOOTCLOCKFRO12M_CORE_CLOCK; +} +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO24M ********************** + ******************************************************************************/ +/* clang-format off */ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!Configuration +name: BOARD_BootClockFRO24M +outputs: +- {id: CLK_1M_clock.outFreq, value: 1 MHz} +- {id: CLK_48M_clock.outFreq, value: 48 MHz} +- {id: CPU_clock.outFreq, value: 24 MHz} +- {id: FRO_12M_clock.outFreq, value: 12 MHz} +- {id: FRO_HF_DIV_clock.outFreq, value: 48 MHz} +- {id: FRO_HF_clock.outFreq, value: 48 MHz} +- {id: MAIN_clock.outFreq, value: 48 MHz} +- {id: Slow_clock.outFreq, value: 6 MHz} +- {id: System_clock.outFreq, value: 24 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +settings: +- {id: MRCC.FREQMEREFCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FREQMETARGETCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.OSTIMERCLKSEL.sel, value: VBAT.CLK16K_1} +- {id: SYSCON.AHBCLKDIV.scale, value: '2', locked: true} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ +/* clang-format on */ + +/******************************************************************************* + * Variables for BOARD_BootClockFRO24M configuration + ******************************************************************************/ +/******************************************************************************* + * Code for BOARD_BootClockFRO24M configuration + ******************************************************************************/ +void BOARD_BootClockFRO24M(void) +{ + uint32_t coreFreq; + spc_active_mode_core_ldo_option_t ldoOption; + spc_sram_voltage_config_t sramOption; + + /* Get the CPU Core frequency */ + coreFreq = CLOCK_GetCoreSysClkFreq(); + + /* The flow of increasing voltage and frequency */ + if (coreFreq <= BOARD_BOOTCLOCKFRO24M_CORE_CLOCK) { + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_MidDriveVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x0U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P0V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + } + + CLOCK_SetupFROHFClocking(48000000U); /*!< Enable FRO HF(48MHz) output */ + + CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */ + + CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /* !< Switch MAIN_CLK to FRO_HF */ + + /* The flow of decreasing voltage and frequency */ + if (coreFreq > BOARD_BOOTCLOCKFRO24M_CORE_CLOCK) { + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x0U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P0V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_MidDriveVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + } + + /*!< Set up clock selectors - Attach clocks to the peripheries */ + + /*!< Set up dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 2U); /* !< Set AHBCLKDIV divider to value 2 */ + CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + + /* Set SystemCoreClock variable */ + SystemCoreClock = BOARD_BOOTCLOCKFRO24M_CORE_CLOCK; +} +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO48M ********************** + ******************************************************************************/ +/* clang-format off */ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!Configuration +name: BOARD_BootClockFRO48M +outputs: +- {id: CLK_1M_clock.outFreq, value: 1 MHz} +- {id: CLK_48M_clock.outFreq, value: 48 MHz} +- {id: CPU_clock.outFreq, value: 48 MHz} +- {id: FRO_12M_clock.outFreq, value: 12 MHz} +- {id: FRO_HF_DIV_clock.outFreq, value: 48 MHz} +- {id: FRO_HF_clock.outFreq, value: 48 MHz} +- {id: MAIN_clock.outFreq, value: 48 MHz} +- {id: Slow_clock.outFreq, value: 12 MHz} +- {id: System_clock.outFreq, value: 48 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +settings: +- {id: MRCC.FREQMEREFCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FREQMETARGETCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.OSTIMERCLKSEL.sel, value: VBAT.CLK16K_1} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ +/* clang-format on */ + +/******************************************************************************* + * Variables for BOARD_BootClockFRO48M configuration + ******************************************************************************/ +/******************************************************************************* + * Code for BOARD_BootClockFRO48M configuration + ******************************************************************************/ +void BOARD_BootClockFRO48M(void) +{ + uint32_t coreFreq; + spc_active_mode_core_ldo_option_t ldoOption; + spc_sram_voltage_config_t sramOption; + + /* Get the CPU Core frequency */ + coreFreq = CLOCK_GetCoreSysClkFreq(); + + /* The flow of increasing voltage and frequency */ + if (coreFreq <= BOARD_BOOTCLOCKFRO48M_CORE_CLOCK) { + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_MidDriveVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x1U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P0V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + } + + CLOCK_SetupFROHFClocking(48000000U); /*!< Enable FRO HF(48MHz) output */ + + CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */ + + CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /* !< Switch MAIN_CLK to FRO_HF */ + + /* The flow of decreasing voltage and frequency */ + if (coreFreq > BOARD_BOOTCLOCKFRO48M_CORE_CLOCK) { + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x1U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P0V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_MidDriveVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + } + + /*!< Set up clock selectors - Attach clocks to the peripheries */ + + /*!< Set up dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + + /* Set SystemCoreClock variable */ + SystemCoreClock = BOARD_BOOTCLOCKFRO48M_CORE_CLOCK; +} +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO64M ********************** + ******************************************************************************/ +/* clang-format off */ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!Configuration +name: BOARD_BootClockFRO64M +outputs: +- {id: CLK_1M_clock.outFreq, value: 1 MHz} +- {id: CLK_48M_clock.outFreq, value: 48 MHz} +- {id: CPU_clock.outFreq, value: 64 MHz} +- {id: FRO_12M_clock.outFreq, value: 12 MHz} +- {id: FRO_HF_DIV_clock.outFreq, value: 64 MHz} +- {id: FRO_HF_clock.outFreq, value: 64 MHz} +- {id: MAIN_clock.outFreq, value: 64 MHz} +- {id: Slow_clock.outFreq, value: 16 MHz} +- {id: System_clock.outFreq, value: 64 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +settings: +- {id: VDD_CORE, value: voltage_1v1} +- {id: MRCC.FREQMEREFCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FREQMETARGETCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FROHFDIV.scale, value: '1', locked: true} +- {id: MRCC.OSTIMERCLKSEL.sel, value: VBAT.CLK16K_1} +- {id: SYSCON.AHBCLKDIV.scale, value: '1', locked: true} +sources: +- {id: SCG.FIRC.outFreq, value: 64 MHz} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ +/* clang-format on */ + +/******************************************************************************* + * Variables for BOARD_BootClockFRO64M configuration + ******************************************************************************/ +/******************************************************************************* + * Code for BOARD_BootClockFRO64M configuration + ******************************************************************************/ +void BOARD_BootClockFRO64M(void) +{ + uint32_t coreFreq; + spc_active_mode_core_ldo_option_t ldoOption; + spc_sram_voltage_config_t sramOption; + + /* Get the CPU Core frequency */ + coreFreq = CLOCK_GetCoreSysClkFreq(); + + /* The flow of increasing voltage and frequency */ + if (coreFreq <= BOARD_BOOTCLOCKFRO64M_CORE_CLOCK) { + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_NormalVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x1U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P1V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + } + + CLOCK_SetupFROHFClocking(64000000U); /*!< Enable FRO HF(64MHz) output */ + + CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */ + + CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /* !< Switch MAIN_CLK to FRO_HF */ + + /* The flow of decreasing voltage and frequency */ + if (coreFreq > BOARD_BOOTCLOCKFRO64M_CORE_CLOCK) { + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x1U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P1V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_NormalVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + } + + /*!< Set up clock selectors - Attach clocks to the peripheries */ + + /*!< Set up dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + + /* Set SystemCoreClock variable */ + SystemCoreClock = BOARD_BOOTCLOCKFRO64M_CORE_CLOCK; +} +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO96M ********************** + ******************************************************************************/ +/* clang-format off */ +/* TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!Configuration +name: BOARD_BootClockFRO96M +called_from_default_init: true +outputs: +- {id: CLK_1M_clock.outFreq, value: 1 MHz} +- {id: CLK_48M_clock.outFreq, value: 48 MHz} +- {id: CPU_clock.outFreq, value: 96 MHz} +- {id: FRO_12M_clock.outFreq, value: 12 MHz} +- {id: FRO_HF_DIV_clock.outFreq, value: 96 MHz} +- {id: FRO_HF_clock.outFreq, value: 96 MHz} +- {id: MAIN_clock.outFreq, value: 96 MHz} +- {id: Slow_clock.outFreq, value: 24 MHz} +- {id: System_clock.outFreq, value: 96 MHz} +- {id: UTICK_clock.outFreq, value: 1 MHz} +settings: +- {id: VDD_CORE, value: voltage_1v1} +- {id: CLKOUTDIV_HALT, value: Enable} +- {id: MRCC.FREQMEREFCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FREQMETARGETCLKSEL.sel, value: MRCC.aoi0_out0} +- {id: MRCC.FROHFDIV.scale, value: '1', locked: true} +- {id: MRCC.OSTIMERCLKSEL.sel, value: VBAT.CLK16K_1} +- {id: SYSCON.AHBCLKDIV.scale, value: '1', locked: true} +sources: +- {id: SCG.FIRC.outFreq, value: 96 MHz} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/ +/* clang-format on */ + +/******************************************************************************* + * Variables for BOARD_BootClockFRO96M configuration + ******************************************************************************/ +/******************************************************************************* + * Code for BOARD_BootClockFRO96M configuration + ******************************************************************************/ +void BOARD_BootClockFRO96M(void) +{ + uint32_t coreFreq; + spc_active_mode_core_ldo_option_t ldoOption; + spc_sram_voltage_config_t sramOption; + + /* Get the CPU Core frequency */ + coreFreq = CLOCK_GetCoreSysClkFreq(); + + /* The flow of increasing voltage and frequency */ + if (coreFreq <= BOARD_BOOTCLOCKFRO96M_CORE_CLOCK) { + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_NormalVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x2U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P1V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + } + + CLOCK_SetupFROHFClocking(96000000U); /*!< Enable FRO HF(96MHz) output */ + + CLOCK_SetupFRO12MClocking(); /*!< Setup FRO12M clock */ + + CLOCK_AttachClk(kFRO_HF_to_MAIN_CLK); /* !< Switch MAIN_CLK to FRO_HF */ + + /* The flow of decreasing voltage and frequency */ + if (coreFreq > BOARD_BOOTCLOCKFRO96M_CORE_CLOCK) { + /* Configure Flash to support different voltage level and frequency */ + FMU0->FCTRL = (FMU0->FCTRL & ~((uint32_t)FMU_FCTRL_RWSC_MASK)) | (FMU_FCTRL_RWSC(0x2U)); + /* Specifies the operating voltage for the SRAM's read/write timing margin */ + sramOption.operateVoltage = kSPC_sramOperateAt1P1V; + sramOption.requestVoltageUpdate = true; + (void)SPC_SetSRAMOperateVoltage(SPC0, &sramOption); + /* Set the LDO_CORE VDD regulator level */ + ldoOption.CoreLDOVoltage = kSPC_CoreLDO_NormalVoltage; + ldoOption.CoreLDODriveStrength = kSPC_CoreLDO_NormalDriveStrength; + (void)SPC_SetActiveModeCoreLDORegulatorConfig(SPC0, &ldoOption); + } + + /*!< Set up clock selectors - Attach clocks to the peripheries */ + + /*!< Set up dividers */ + CLOCK_SetClockDiv(kCLOCK_DivAHBCLK, 1U); /* !< Set AHBCLKDIV divider to value 1 */ + CLOCK_SetClockDiv(kCLOCK_DivFRO_HF_DIV, 1U); /* !< Set FROHFDIV divider to value 1 */ + + /* Set SystemCoreClock variable */ + SystemCoreClock = BOARD_BOOTCLOCKFRO96M_CORE_CLOCK; +} diff --git a/hw/bsp/mcx/boards/frdm_mcxa156/clock_config.h b/hw/bsp/mcx/boards/frdm_mcxa156/clock_config.h new file mode 100644 index 000000000..db80b79f3 --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa156/clock_config.h @@ -0,0 +1,170 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +#ifndef _CLOCK_CONFIG_H_ +#define _CLOCK_CONFIG_H_ + +#include "fsl_common.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + ************************ BOARD_InitBootClocks function ************************ + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes default configuration of clocks. + * + */ +void BOARD_InitBootClocks(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO12M ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockFRO12M configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKFRO12M_CORE_CLOCK 12000000U /*!< Core clock frequency: 12000000Hz */ + + +/******************************************************************************* + * API for BOARD_BootClockFRO12M configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockFRO12M(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO24M ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockFRO24M configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKFRO24M_CORE_CLOCK 24000000U /*!< Core clock frequency: 24000000Hz */ + + +/******************************************************************************* + * API for BOARD_BootClockFRO24M configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockFRO24M(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO48M ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockFRO48M configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKFRO48M_CORE_CLOCK 48000000U /*!< Core clock frequency: 48000000Hz */ + + +/******************************************************************************* + * API for BOARD_BootClockFRO48M configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockFRO48M(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO64M ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockFRO64M configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKFRO64M_CORE_CLOCK 64000000U /*!< Core clock frequency: 64000000Hz */ + + +/******************************************************************************* + * API for BOARD_BootClockFRO64M configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockFRO64M(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +/******************************************************************************* + ******************** Configuration BOARD_BootClockFRO96M ********************** + ******************************************************************************/ +/******************************************************************************* + * Definitions for BOARD_BootClockFRO96M configuration + ******************************************************************************/ +#define BOARD_BOOTCLOCKFRO96M_CORE_CLOCK 96000000U /*!< Core clock frequency: 96000000Hz */ + + +/******************************************************************************* + * API for BOARD_BootClockFRO96M configuration + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus*/ + +/*! + * @brief This function executes configuration of clocks. + * + */ +void BOARD_BootClockFRO96M(void); + +#if defined(__cplusplus) +} +#endif /* __cplusplus*/ + +#endif /* _CLOCK_CONFIG_H_ */ + diff --git a/hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.c b/hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.c new file mode 100644 index 000000000..317c311b5 --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.c @@ -0,0 +1,144 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +!!GlobalInfo +product: Pins v15.0 +processor: MCXA156 +package_id: MCXA156VLL +mcu_data: ksdk2_0 +processor_version: 0.15.0 + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +#include "fsl_common.h" +#include "fsl_port.h" +#include "pin_mux.h" + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitBootPins + * Description : Calls initialization functions. + * + * END ****************************************************************************************************************/ +void BOARD_InitBootPins(void) +{ + BOARD_InitPins(); +} + +/* clang-format off */ +/* + * TEXT BELOW IS USED AS SETTING FOR TOOLS ************************************* +BOARD_InitPins: +- options: {callFromInitBoot: 'true', coreID: cm33_core0, enableClock: 'true'} +- pin_list: + - {pin_num: '78', peripheral: LPUART0, signal: RX, pin_signal: P0_2/TDO/SWO/LPUART0_RXD/LPSPI0_SCK/CT0_MAT0/UTICK_CAP0/FLEXIO0_D2, slew_rate: fast, open_drain: disable, + drive_strength: low, pull_select: up, pull_enable: enable, input_buffer: enable, invert_input: normal} + - {pin_num: '79', peripheral: LPUART0, signal: TX, pin_signal: P0_3/TDI/LPUART0_TXD/LPSPI0_SDO/CT0_MAT1/UTICK_CAP1/FLEXIO0_D3/CMP0_OUT, slew_rate: fast, open_drain: disable, + drive_strength: low, pull_select: up, pull_enable: enable, input_buffer: enable, invert_input: normal} + * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS *********** + */ +/* clang-format on */ + +/* FUNCTION ************************************************************************************************************ + * + * Function Name : BOARD_InitPins + * Description : Configures pin routing and optionally pin electrical features. + * + * END ****************************************************************************************************************/ +void BOARD_InitPins(void) +{ + + RESET_PeripheralReset(kLPUART0_RST_SHIFT_RSTn); + CLOCK_SetClockDiv(kCLOCK_DivLPUART0, 1u); + CLOCK_AttachClk(kFRO12M_to_LPUART0); + + /* GPIO3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GateGPIO3); + /* PORT3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT3); + /* GPIO3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kGPIO3_RST_SHIFT_RSTn); + /* PORT3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); + + /* GPIO3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GateGPIO0); + /* PORT3: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT0); + /* GPIO3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kGPIO0_RST_SHIFT_RSTn); + /* PORT3 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); + + /* PORT0: Peripheral clock is enabled */ + CLOCK_EnableClock(kCLOCK_GatePORT0); + /* LPUART0 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kLPUART0_RST_SHIFT_RSTn); + /* PORT0 peripheral is released from reset */ + RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); + + const port_pin_config_t port0_2_pin78_config = {/* Internal pull-up resistor is enabled */ + kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + kPORT_NormalDriveStrength, + /* Pin is configured as LPUART0_RXD */ + kPORT_MuxAlt2, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT0_2 (pin 78) is configured as LPUART0_RXD */ + PORT_SetPinConfig(PORT0, 2U, &port0_2_pin78_config); + + const port_pin_config_t port0_3_pin79_config = {/* Internal pull-up resistor is enabled */ + kPORT_PullUp, + /* Low internal pull resistor value is selected. */ + kPORT_LowPullResistor, + /* Fast slew rate is configured */ + kPORT_FastSlewRate, + /* Passive input filter is disabled */ + kPORT_PassiveFilterDisable, + /* Open drain output is disabled */ + kPORT_OpenDrainDisable, + /* Low drive strength is configured */ + kPORT_LowDriveStrength, + /* Normal drive strength is configured */ + kPORT_NormalDriveStrength, + /* Pin is configured as LPUART0_TXD */ + kPORT_MuxAlt2, + /* Digital input enabled */ + kPORT_InputBufferEnable, + /* Digital input is not inverted */ + kPORT_InputNormal, + /* Pin Control Register fields [15:0] are not locked */ + kPORT_UnlockRegister}; + /* PORT0_3 (pin 79) is configured as LPUART0_TXD */ + PORT_SetPinConfig(PORT0, 3U, &port0_3_pin79_config); +} +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.h b/hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.h new file mode 100644 index 000000000..fb7d1fc04 --- /dev/null +++ b/hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.h @@ -0,0 +1,51 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*********************************************************************************************************************** + * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file + * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. + **********************************************************************************************************************/ + +#ifndef _PIN_MUX_H_ +#define _PIN_MUX_H_ + +/*! + * @addtogroup pin_mux + * @{ + */ + +/*********************************************************************************************************************** + * API + **********************************************************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @brief Calls initialization functions. + * + */ +void BOARD_InitBootPins(void); + +/*! + * @brief Configures pin routing and optionally pin electrical features. + * + */ +void BOARD_InitPins(void); + +#if defined(__cplusplus) +} +#endif + +/*! + * @} + */ +#endif /* _PIN_MUX_H_ */ + +/*********************************************************************************************************************** + * EOF + **********************************************************************************************************************/ diff --git a/hw/bsp/mcx/boards/frdm_mcxn947/board.h b/hw/bsp/mcx/boards/frdm_mcxn947/board.h index a35b6818a..bb15620ef 100644 --- a/hw/bsp/mcx/boards/frdm_mcxn947/board.h +++ b/hw/bsp/mcx/boards/frdm_mcxn947/board.h @@ -49,17 +49,22 @@ #define BUTTON_STATE_ACTIVE 0 // UART -#define UART_DEV LPUART4 +#define UART_DEV LPUART4 +#define LP_FLEXCOMM_INST 4 + +#include "fsl_lpflexcomm.h" static inline void board_uart_init_clock(void) { + /* attach FRO 12M to FLEXCOMM4 */ + + LP_FLEXCOMM_Init(LP_FLEXCOMM_INST, LP_FLEXCOMM_PERIPH_LPUART); + CLOCK_SetClkDiv(kCLOCK_DivFlexcom4Clk, 1u); CLOCK_AttachClk(kFRO12M_to_FLEXCOMM4); RESET_ClearPeripheralReset(kFC4_RST_SHIFT_RSTn); -} -//#define UART_RX_PINMUX 0, 24, IOCON_PIO_DIG_FUNC1_EN -//#define UART_TX_PINMUX 0, 25, IOCON_PIO_DIG_FUNC1_EN +} // XTAL #define XTAL0_CLK_HZ (24 * 1000 * 1000U) diff --git a/hw/bsp/mcx/drivers/spc/fsl_spc.c b/hw/bsp/mcx/drivers/spc/fsl_spc.c new file mode 100644 index 000000000..c6a9b2932 --- /dev/null +++ b/hw/bsp/mcx/drivers/spc/fsl_spc.c @@ -0,0 +1,1680 @@ +/* + * Copyright 2022-2024 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_spc.h" + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.mcx_spc" +#endif + +/* + * $Coverage Justification Reference$ + * + * $Justification spc_c_ref_1$ + * The SPC busy status flag is too short to get coverage data. + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +/*! + * brief Gets selected power domain's requested low power mode. + * + * param base SPC peripheral base address. + * param powerDomainId Power Domain Id, please refer to spc_power_domain_id_t. + * + * return The selected power domain's requested low power mode, please refer to spc_power_domain_low_power_mode_t. + */ +spc_power_domain_low_power_mode_t SPC_GetPowerDomainLowPowerMode(SPC_Type *base, spc_power_domain_id_t powerDomainId) +{ + assert((uint8_t)powerDomainId < SPC_PD_STATUS_COUNT); + + uint32_t val; + + val = ((base->PD_STATUS[(uint8_t)powerDomainId] & SPC_PD_STATUS_LP_MODE_MASK) >> SPC_PD_STATUS_LP_MODE_SHIFT); + return (spc_power_domain_low_power_mode_t)val; +} + +/*! + * brief Gets Isolation status for each power domains. + * + * This function gets the status which indicates whether certain + * peripheral and the IO pads are in a latched state as a result + * of having been in POWERDOWN mode. + * + * param base SPC peripheral base address. + * return Current isolation status for each power domains. + */ +uint8_t SPC_GetPeriphIOIsolationStatus(SPC_Type *base) +{ + uint32_t reg; + + reg = base->SC; + return (uint8_t)((reg & SPC_SC_ISO_CLR_MASK) >> SPC_SC_ISO_CLR_SHIFT); +} + +/*! + * brief Configs Low power request output pin. + * + * This function configs the low power request output pin + * + * param base SPC peripheral base address. + * param config Pointer the spc_LowPower_Request_config_t structure. + */ +void SPC_SetLowPowerRequestConfig(SPC_Type *base, const spc_lowpower_request_config_t *config) +{ + assert(config != NULL); + + uint32_t reg; + + reg = base->LPREQ_CFG; + reg &= ~(SPC_LPREQ_CFG_LPREQOE_MASK | SPC_LPREQ_CFG_LPREQPOL_MASK | SPC_LPREQ_CFG_LPREQOV_MASK); + + if (config->enable) + { + reg |= SPC_LPREQ_CFG_LPREQOE_MASK | SPC_LPREQ_CFG_LPREQPOL((uint8_t)(config->polarity)) | + SPC_LPREQ_CFG_LPREQOV((uint8_t)(config->override)); + } + else + { + reg &= ~SPC_LPREQ_CFG_LPREQOE_MASK; + } + + base->LPREQ_CFG = reg; +} + +#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) +/*! + * brief Configures VDD Core Glitch detector, including ripple counter selection, timeout value and so on. + * + * param base SPC peripheral base address. + * param config Pointer to the structure in type of spc_vdd_core_glitch_detector_config_t. + */ +void SPC_ConfigVddCoreGlitchDetector(SPC_Type *base, const spc_vdd_core_glitch_detector_config_t *config) +{ + assert(config != NULL); + + uint32_t reg; + + reg = (base->VDD_CORE_GLITCH_DETECT_SC) & + ~(SPC_VDD_CORE_GLITCH_DETECT_SC_CNT_SELECT_MASK | SPC_VDD_CORE_GLITCH_DETECT_SC_TIMEOUT_MASK | + SPC_VDD_CORE_GLITCH_DETECT_SC_RE_MASK | SPC_VDD_CORE_GLITCH_DETECT_SC_IE_MASK); + + reg |= SPC_VDD_CORE_GLITCH_DETECT_SC_CNT_SELECT(config->rippleCounterSelect) | + SPC_VDD_CORE_GLITCH_DETECT_SC_TIMEOUT(config->resetTimeoutValue) | + SPC_VDD_CORE_GLITCH_DETECT_SC_RE(config->enableReset) | + SPC_VDD_CORE_GLITCH_DETECT_SC_IE(config->enableInterrupt); + + base->VDD_CORE_GLITCH_DETECT_SC = reg; +} +#endif + +/*! + * brief Set SRAM operate voltage. + * + * param base SPC peripheral base address. + * param config The pointer to spc_sram_voltage_config_t, specifies the configuration of sram voltage. + */ +void SPC_SetSRAMOperateVoltage(SPC_Type *base, const spc_sram_voltage_config_t *config) +{ + assert(config != NULL); + + uint32_t reg = 0UL; + + reg |= SPC_SRAMCTL_VSM(config->operateVoltage); + + base->SRAMCTL = reg; + + if (config->requestVoltageUpdate) + { + base->SRAMCTL |= SPC_SRAMCTL_REQ_MASK; + while ((base->SRAMCTL & SPC_SRAMCTL_ACK_MASK) == 0UL) + { + /* Wait until acknowledged */ + ; + } + base->SRAMCTL &= ~SPC_SRAMCTL_REQ_MASK; + } +} + +/*! + * brief Configs Bandgap mode in Active mode. + * + * @note To disable bandgap in Active mode: + * 1. Disable all LVD's and HVD's in active mode; + * 2. Disable Glitch detect; + * 3. Configrue LDO's and DCDC to low drive strength in active mode; + * 4. Invoke this function to disable bandgap in active mode; + * otherwise the error status will be reported. + * + * @note Some other system resources(such as PLL, CMP) require bandgap to be enabled, to disable bandgap please + * take care of other system resources. + * + * param base SPC peripheral base address. + * param mode The Bandgap mode be selected. + * + * retval kStatus_SPC_BandgapModeWrong The Bandgap can not be disabled in active mode. + * retval kStatus_Success Config Bandgap mode in Active power mode successful. + */ +status_t SPC_SetActiveModeBandgapModeConfig(SPC_Type *base, spc_bandgap_mode_t mode) +{ + uint32_t reg; + uint32_t state; + + reg = base->ACTIVE_CFG; + + if (mode == kSPC_BandgapDisabled) + { + state = SPC_GetActiveModeVoltageDetectStatus(base); + + /* If any of the LVD/HVDs are kept enabled, bandgap mode must be enabled with buffer disabled. */ + if (state != 0UL) + { + return kStatus_SPC_BandgapModeWrong; + } + + /* The bandgap mode must be enabled if any regulators' drive strength set as Normal. */ +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + if ((base->ACTIVE_CFG & SPC_ACTIVE_CFG_SYSLDO_VDD_DS_MASK) == + SPC_ACTIVE_CFG_SYSLDO_VDD_DS(kSPC_SysLDO_NormalDriveStrength)) + { + return kStatus_SPC_BandgapModeWrong; + } +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) + if ((base->ACTIVE_CFG & SPC_ACTIVE_CFG_DCDC_VDD_DS_MASK) == SPC_ACTIVE_CFG_DCDC_VDD_DS(kSPC_DCDC_NormalVoltage)) + { + return kStatus_SPC_BandgapModeWrong; + } +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + +#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) + /* state of GLITCH_DETECT_DISABLE will be ignored if bandgap is disabled. */ + if ((base->ACTIVE_CFG & SPC_ACTIVE_CFG_GLITCH_DETECT_DISABLE_MASK) == 0UL) + { + return kStatus_SPC_BandgapModeWrong; + } +#endif +#if defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS + if ((base->ACTIVE_CFG & SPC_ACTIVE_CFG_CORELDO_VDD_DS_MASK) == + SPC_ACTIVE_CFG_CORELDO_VDD_DS(kSPC_CoreLDO_NormalDriveStrength)) + { + return kStatus_SPC_BandgapModeWrong; + } +#endif /* FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS */ + } + + reg &= ~SPC_ACTIVE_CFG_BGMODE_MASK; + reg |= SPC_ACTIVE_CFG_BGMODE(mode); + + base->ACTIVE_CFG = reg; + + return kStatus_Success; +} + +/*! + * brief Configs Bandgap mode in Low Power mode. + * + * @note To disable Bandgap in Low-power mode: + * 1. Disable all LVD's ad HVD's in low power mode; + * 2. Disable Glitch detect in low power mode; + * 3. Configure LDO's and DCDC to low drive strength in low power mode; + * 4. Disable bandgap in low power mode; + * Otherwise, the error status will be reported. + * + * @note Some other system resources(such as PLL, CMP) require bandgap to be enabled, to disable bandgap please + * take care of other system resources. + * + * param base SPC peripheral base address. + * param mode The Bandgap mode be selected. + * + * retval kStatus_SPC_BandgapModeWrong The bandgap mode setting in Low Power mode is wrong. + * retval kStatus_Success Config Bandgap mode in Low Power power mode successful. + */ +status_t SPC_SetLowPowerModeBandgapmodeConfig(SPC_Type *base, spc_bandgap_mode_t mode) +{ + uint32_t reg; + uint32_t state; + + reg = base->LP_CFG; + + if (mode == kSPC_BandgapDisabled) + { + state = (uint32_t)SPC_GetLowPowerModeVoltageDetectStatus(base); + + /* If any of the LVD/HVDs are kept enabled, bandgap mode must be enabled with buffer disabled. */ + if (state != 0UL) + { + return kStatus_SPC_BandgapModeWrong; + } + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) + if ((base->LP_CFG & SPC_LP_CFG_DCDC_VDD_DS_MASK) == SPC_LP_CFG_DCDC_VDD_DS(kSPC_DCDC_NormalDriveStrength)) + { + return kStatus_SPC_BandgapModeWrong; + } +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + if ((base->LP_CFG & SPC_LP_CFG_SYSLDO_VDD_DS_MASK) == SPC_LP_CFG_SYSLDO_VDD_DS(kSPC_SysLDO_NormalDriveStrength)) + { + return kStatus_SPC_BandgapModeWrong; + } +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + + if ((base->LP_CFG & SPC_LP_CFG_CORELDO_VDD_DS_MASK) == + SPC_LP_CFG_CORELDO_VDD_DS(kSPC_CoreLDO_NormalDriveStrength)) + { + return kStatus_SPC_BandgapModeWrong; + } + +#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) + /* state of GLITCH_DETECT_DISABLE will be ignored if bandgap is disabled. */ + if ((base->LP_CFG & SPC_LP_CFG_GLITCH_DETECT_DISABLE_MASK) == 0UL) + { + return kStatus_SPC_BandgapModeWrong; + } +#endif + } + + reg &= ~SPC_LP_CFG_BGMODE_MASK; + reg |= SPC_LP_CFG_BGMODE(mode); + base->LP_CFG = reg; + + return kStatus_Success; +} + +/*! + * brief Configs CORE voltage detect options. + * + * This function configs CORE voltage detect options. + * Note: Setting both the voltage detect interrupt and reset + * enable will cause interrupt to be generated on exit from reset. + * If those conditioned is not desired, interrupt/reset only one is enabled. + * + * param base SPC peripheral base address. + * param config Pointer to spc_core_voltage_detect_config_t structure. + */ +void SPC_SetCoreVoltageDetectConfig(SPC_Type *base, const spc_core_voltage_detect_config_t *config) +{ + assert(config != NULL); + + uint32_t reg = 0UL; + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) && FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) + reg |= (config->option.HVDInterruptEnable) ? SPC_VD_CORE_CFG_HVDIE(1U) : SPC_VD_CORE_CFG_HVDIE(0U); + reg |= (config->option.HVDResetEnable) ? SPC_VD_CORE_CFG_HVDRE(1U) : SPC_VD_CORE_CFG_HVDRE(0U); +#endif /* FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD */ + reg |= (config->option.LVDInterruptEnable) ? SPC_VD_CORE_CFG_LVDIE(1U) : SPC_VD_CORE_CFG_LVDIE(0U); + reg |= (config->option.LVDResetEnable) ? SPC_VD_CORE_CFG_LVDRE(1U) : SPC_VD_CORE_CFG_LVDRE(0U); + + base->VD_CORE_CFG = reg; +} + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) && FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) +/*! + * brief Enables the Core High Voltage Detector in Active mode. + * + * note If the CORE_LDO high voltage detect is enabled in Active mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low. + * + * param base SPC peripheral base address. + * param enable Enable/Disable Core HVD. + * true - Enable Core High voltage detector in active mode. + * false - Disable Core High voltage detector in active mode. + * + * retval kStatus_Success Enable Core High Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeCoreHighVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->ACTIVE_CFG |= SPC_ACTIVE_CFG_CORE_HVDE_MASK; + } + else + { + base->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_CORE_HVDE_MASK; + } + + return status; +} + +/*! + * brief Enables the Core High Voltage Detector in Low Power mode. + * + * note If the CORE_LDO high voltage detect is enabled in Low Power mode, + * please note that the bandgap must be enabled and the drive strength of each regulator + * must not set to low in low power mode. + * + * param base SPC peripheral base address. + * param enable Enable/Disable Core HVD. + * true - Enable Core High voltage detector in low power mode. + * false - Disable Core High voltage detector in low power mode. + * + * retval kStatus_Success Enable Core High Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeCoreHighVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->LP_CFG |= SPC_LP_CFG_CORE_HVDE_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_CORE_HVDE_MASK; + } + + return status; +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD */ + +/*! + * brief Enables the Core VDD Low Voltage Detector in Active mode. + * + * note If the Core VDD high voltage detect is enabled in Active mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low. + * + * param base SPC peripheral base address. + * param enable Enable/Disable Core LVD. + * true - Enable Core Low voltage detector in active mode. + * false - Disable Core Low voltage detector in active mode. + * + * retval kStatus_Success Enable Core Low Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeCoreLowVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->ACTIVE_CFG |= SPC_ACTIVE_CFG_CORE_LVDE_MASK; + } + else + { + base->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_CORE_LVDE_MASK; + } + + return status; +} + +/*! + * brief Enables the Core Low Voltage Detector in Low Power mode. + * + * note If the Core VDD low voltage detect is enabled in Low Power mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low in Low Power mode. + * + * param base SPC peripheral base address. + * param enable Enable/Disable Core HVD. + * true - Enable Core Low voltage detector in low power mode. + * false - Disable Core Low voltage detector in low power mode. + * + * retval kStatus_Success Enable Core Low Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeCoreLowVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->LP_CFG |= SPC_LP_CFG_CORE_LVDE_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_CORE_LVDE_MASK; + } + + return status; +} + +/*! + * brief Set system VDD Low-voltage level selection. + * + * This function selects the system VDD low-voltage level. Changing system VDD low-voltage level + * must be done after disabling the System VDD low voltage reset and interrupt. + * + * @deprecated In latest RM, reserved for all devices, will removed in next release. + * + * param base SPC peripheral base address. + * param level System VDD Low-Voltage level selection. See @ref spc_low_voltage_level_select_t for details. + */ +void SPC_SetSystemVDDLowVoltageLevel(SPC_Type *base, spc_low_voltage_level_select_t level) +{ + (void)level; + (void)base; + + /* + uint32_t reg; + + reg = base->VD_SYS_CFG; + + base->VD_SYS_CFG &= ~(SPC_VD_SYS_CFG_LVDRE_MASK | SPC_VD_SYS_CFG_LVDIE_MASK); + reg |= SPC_VD_SYS_CFG_LVSEL(level); + + base->VD_SYS_CFG = reg; */ +} + +/*! + * brief Configs SYS VDD voltage detect options. + * + * This function config SYS voltage detect options. + * Note: Setting both the voltage detect interrupt and reset + * enable will cause interrupt to be generated on exit from reset. + * If those conditioned is not desired, interrupt/reset only one is enabled. + * + * param base SPC peripheral base address. + * param config Pointer to spc_system_voltage_detect_config_t structure. + */ +void SPC_SetSystemVoltageDetectConfig(SPC_Type *base, const spc_system_voltage_detect_config_t *config) +{ + assert(config != NULL); + + uint32_t reg = 0UL; + + reg |= (config->option.HVDInterruptEnable) ? SPC_VD_SYS_CFG_HVDIE(1U) : SPC_VD_SYS_CFG_HVDIE(0U); + reg |= (config->option.LVDInterruptEnable) ? SPC_VD_SYS_CFG_LVDIE(1U) : SPC_VD_SYS_CFG_LVDIE(0U); + reg |= (config->option.HVDResetEnable) ? SPC_VD_SYS_CFG_HVDRE(1U) : SPC_VD_SYS_CFG_HVDRE(0U); + reg |= (config->option.LVDResetEnable) ? SPC_VD_SYS_CFG_LVDRE(1U) : SPC_VD_SYS_CFG_LVDRE(0U); + + base->VD_SYS_CFG = reg; + + (void)(config->level); + /* SPC_SetSystemVDDLowVoltageLevel(base, config->level); */ +} + +/*! + * brief Enables the System VDD High Voltage Detector in Active mode. + * + * note If the System_LDO high voltage detect is enabled in Active mode, + * please note that the bandgap must be enabled and the drive strength of + * each regulator must not set to low in Active mode. + * + * param base SPC peripheral base address. + * param enable Enable/Disable System HVD. + * true - Enable System High voltage detector in active mode. + * false - Disable System High voltage detector in active mode. + * + * retval kStatus_Success Enable System High Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeSystemHighVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->ACTIVE_CFG |= SPC_ACTIVE_CFG_SYS_HVDE_MASK; + } + else + { + base->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_SYS_HVDE_MASK; + } + + return status; +} + +/*! + * brief Enables the System VDD Low Voltage Detector in Active mode. + * + * note If the System_LDO low voltage detect is enabled in Active mode, + * please note that the bandgap must be enabled and the drive strength of each + * regulator must not set to low in Active mode. + * + * param base SPC peripheral base address. + * param enable Enable/Disable System LVD. + * true - Enable System Low voltage detector in active mode. + * false - Disable System Low voltage detector in active mode. + * + * retval kStatus_Success Enable the System Low Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeSystemLowVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->ACTIVE_CFG |= SPC_ACTIVE_CFG_SYS_LVDE_MASK; + } + else + { + base->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_SYS_LVDE_MASK; + } + + return status; +} + +/*! + * brief Enables the System VDD High Voltage Detector in Low Power mode. + * + * note If the System_LDO high voltage detect is enabled in low power mode, + * please note that the bandgap must be enabled and the drive strength of each + * regulator must not set to low in low power mode. + * + * param base SPC peripheral base address. + * param enable Enable/Disable System HVD. + * true - Enable System High voltage detector in low power mode. + * false - Disable System High voltage detector in low power mode. + * + * retval kStatus_Success Enable System High Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeSystemHighVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->LP_CFG |= SPC_LP_CFG_SYS_HVDE_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_SYS_HVDE_MASK; + } + + return status; +} + +/*! + * brief Enables the System VDD Low Voltage Detector in Low Power mode. + * + * note If the System_LDO low voltage detect is enabled in Low Power mode, + * please note that the bandgap must be enabled and the drive strength of each + * regulator must not set to low in Low Power mode. + * + * param base SPC peripheral base address. + * param enable Enable/Disable System HVD. + * true - Enable System Low voltage detector in low power mode. + * false - Disable System Low voltage detector in low power mode. + * + * retval kStatus_Success Enable System Low Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeSystemLowVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->LP_CFG |= SPC_LP_CFG_SYS_LVDE_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_SYS_LVDE_MASK; + } + + return status; +} + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) && FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) +/*! + * brief Set IO VDD Low-Voltage level selection. + * + * This function selects the IO VDD Low-voltage level. Changing IO VDD low-voltage level + * must be done after disabling the IO VDD low voltage reset and interrupt. + * + * param base SPC peripheral base address. + * param level IO VDD Low-voltage level selection. + */ +void SPC_SetIOVDDLowVoltageLevel(SPC_Type *base, spc_low_voltage_level_select_t level) +{ + uint32_t reg; + + reg = base->VD_IO_CFG; + + base->VD_IO_CFG &= ~(SPC_VD_IO_CFG_LVDRE_MASK | SPC_VD_IO_CFG_LVDIE_MASK | SPC_VD_IO_CFG_LVSEL_MASK); + reg |= SPC_VD_IO_CFG_LVSEL(level); + + base->VD_IO_CFG = reg; +} + +/*! + * brief Configs IO VDD voltage detect options. + * + * This function config IO voltage detect options. + * Note: Setting both the voltage detect interrupt and reset + * enable will cause interrupt to be generated on exit from reset. + * If those conditioned is not desired, interrupt/reset so only one is enabled. + * + * param base SPC peripheral base address. + * param config Pointer to spc_IO_voltage_detect_config_t structure. + */ +void SPC_SetIOVoltageDetectConfig(SPC_Type *base, const spc_io_voltage_detect_config_t *config) +{ + assert(config != NULL); + + uint32_t reg = 0UL; + + /* Set trip voltage level. */ + SPC_SetIOVDDLowVoltageLevel(base, config->level); + + reg = base->VD_IO_CFG; + reg &= ~(SPC_VD_IO_CFG_LVDRE_MASK | SPC_VD_IO_CFG_LVDIE_MASK | SPC_VD_IO_CFG_HVDRE_MASK | SPC_VD_IO_CFG_HVDIE_MASK); + + reg |= (config->option.HVDInterruptEnable) ? SPC_VD_IO_CFG_HVDIE(1U) : SPC_VD_IO_CFG_HVDIE(0U); + reg |= (config->option.LVDInterruptEnable) ? SPC_VD_IO_CFG_LVDIE(1U) : SPC_VD_IO_CFG_LVDIE(0U); + reg |= (config->option.HVDResetEnable) ? SPC_VD_IO_CFG_HVDRE(1U) : SPC_VD_IO_CFG_HVDRE(0U); + reg |= (config->option.LVDResetEnable) ? SPC_VD_IO_CFG_LVDRE(1U) : SPC_VD_IO_CFG_LVDRE(0U); + + base->VD_IO_CFG = reg; +} + +/*! + * brief Enables the IO VDD High Voltage Detector in Active mode. + * + * note If the IO high voltage detect is enabled in Active mode, + * please note that the bandgap must be enabled and the drive strength + * of each regulator must not set to low in Active mode. + * + * param base SPC peripheral base address. + * param enable Enable/Disable IO HVD. + * true - Enable IO High voltage detector in active mode. + * false - Disable IO High voltage detector in active mode. + * + * retval kStatus_Success Enable IO High Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeIOHighVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->ACTIVE_CFG |= SPC_ACTIVE_CFG_IO_HVDE_MASK; + } + else + { + base->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_IO_HVDE_MASK; + } + + return status; +} + +/*! + * brief Enables the IO VDD Low Voltage Detector in Active mode. + * + * note If the IO low voltage detect is enabled in Active mode, + * please note that the bandgap must be enabled and the drive strength + * of each regulator must not set to low in Active mode. + * + * param base SPC peripheral base address. + * param enable Enable/Disable IO LVD. + * true - Enable IO Low voltage detector in active mode. + * false - Disable IO Low voltage detector in active mode. + * + * retval kStatus_Success Enable IO Low Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeIOLowVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->ACTIVE_CFG |= SPC_ACTIVE_CFG_IO_LVDE_MASK; + } + else + { + base->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_IO_LVDE_MASK; + } + + return status; +} + +/*! + * brief Enables the IO VDD High Voltage Detector in Low Power mode. + * + * note If the IO high voltage detect is enabled in Low Power mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low in Low Power mode. + * + * param base SPC peripheral base address. + * param enable Enable/Disable IO HVD. + * true - Enable IO High voltage detector in low power mode. + * false - Disable IO High voltage detector in low power mode. + * + * retval kStatus_Success Enable IO High Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeIOHighVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->LP_CFG |= SPC_LP_CFG_IO_HVDE_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_IO_HVDE_MASK; + } + + return status; +} + +/*! + * brief Enables the IO VDD Low Voltage Detector in Low Power mode. + * + * note If the IO low voltage detect is enabled in Low Power mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low in Low Power mode. + * + * param base SPC peripheral base address. + * param enable Enable/Disable IO HVD. + * true - Enable IO Low voltage detector in low power mode. + * false - Disable IO Low voltage detector in low power mode. + * + * retval kStatus_Success Enable IO Low Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeIOLowVoltageDetect(SPC_Type *base, bool enable) +{ + status_t status = kStatus_Success; + + if (enable) + { + base->LP_CFG |= SPC_LP_CFG_IO_LVDE_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_IO_LVDE_MASK; + } + + return status; +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD */ + +/*! + * brief Configs external voltage domains + * + * This function configs external voltage domains isolation. + * + * param base SPC peripheral base address. + * param lowPowerIsoMask The mask of external domains isolate enable during low power mode. + * param IsoMask The mask of external domains isolate. + */ +void SPC_SetExternalVoltageDomainsConfig(SPC_Type *base, uint8_t lowPowerIsoMask, uint8_t IsoMask) +{ + uint32_t reg = 0UL; + + reg |= SPC_EVD_CFG_REG_EVDISO(IsoMask) | SPC_EVD_CFG_REG_EVDLPISO(lowPowerIsoMask); + base->EVD_CFG = reg; +} + +/*! + * brief Configs Core LDO Regulator in Active mode. + * + * @note The bandgap must be enabled before invoking this function. + * @note To set Core LDO as low drive strength, all HVDs/LVDs must be disabled previously. + * + * param base SPC peripheral base address. + * param option Pointer to the spc_active_mode_Core_LDO_option_t structure. + * + * retval kStatus_Success Config Core LDO regulator in Active power mode successful. + * retval kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * retval kStatus_SPC_BandgapModeWrong Bandgap should be enabled before invoking this function. + * retval kStatus_SPC_CORELDOLowDriveStrengthIgnore To set Core LDO as low drive strength, + * all LVDs/HVDs must be disabled before invoking this function. + */ +status_t SPC_SetActiveModeCoreLDORegulatorConfig(SPC_Type *base, const spc_active_mode_core_ldo_option_t *option) +{ + assert(option != NULL); + + if ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + return kStatus_SPC_Busy; + } + + /* Check input parameters. */ + /* 1. Bandgap must not be disabled. */ + if (SPC_GetActiveModeBandgapMode(base) == kSPC_BandgapDisabled) + { + return kStatus_SPC_BandgapModeWrong; + } + + /* 2. To set to low drive strength, all LVDs/HVDs must be disabled previously. */ + if ((SPC_GetActiveModeVoltageDetectStatus(base) != 0UL) && + (option->CoreLDODriveStrength == kSPC_CoreLDO_LowDriveStrength)) + { + return kStatus_SPC_CORELDOLowDriveStrengthIgnore; + } + + if ((uint8_t)SPC_GetActiveModeCoreLDOVDDVoltageLevel(base) != (uint8_t)(option->CoreLDOVoltage)) + { +#if defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS + (void)SPC_SetActiveModeCoreLDORegulatorDriveStrength(base, kSPC_CoreLDO_NormalDriveStrength); +#endif /* FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS */ + (void)SPC_SetActiveModeCoreLDORegulatorVoltageLevel(base, option->CoreLDOVoltage); + } + +#if defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS + (void)SPC_SetActiveModeCoreLDORegulatorDriveStrength(base, option->CoreLDODriveStrength); +#endif /* FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS */ + + return kStatus_Success; +} + +/*! + * brief Set Core LDO VDD Regulator Voltage level in Active mode. + * + * @note In active mode, the Core LDO voltage level should only be changed when the + * Core LDO is in normal drive strength. + * + * @note Update Core LDO voltage level will set Busy flag, + * this function return only when busy flag is cleared by hardware + * + * param base SPC peripheral base address. + * param voltageLevel Specify the voltage level of CORE LDO Regulator in Active mode, please + refer to @ref spc_core_ldo_voltage_level_t. + * + * retval kStatus_SPC_CORELDOVoltageSetFail Core LDO voltage level should only be + * changed when the CORE_LDO is in normal drive strength. + * retval kStatus_Success Set Core LDO regulator voltage level in Active power mode successful. + */ +status_t SPC_SetActiveModeCoreLDORegulatorVoltageLevel(SPC_Type *base, spc_core_ldo_voltage_level_t voltageLevel) +{ + if ((uint8_t)voltageLevel != (uint8_t)SPC_GetActiveModeCoreLDOVDDVoltageLevel(base)) + { +#if (defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) + if (SPC_GetActiveModeCoreLDODriveStrength(base) != kSPC_CoreLDO_NormalDriveStrength) + { + return kStatus_SPC_CORELDOVoltageSetFail; + } +#endif /* FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS */ + + base->ACTIVE_CFG = + ((base->ACTIVE_CFG & ~SPC_ACTIVE_CFG_CORELDO_VDD_LVL_MASK) | SPC_ACTIVE_CFG_CORELDO_VDD_LVL(voltageLevel)); + + /* + * $Branch Coverage Justification$ + * $ref spc_c_ref_1$. + */ + while ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + } + } + return kStatus_Success; +} + +#if defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS +/*! + * brief Set Core LDO VDD Regulator Drive Strength in Active mode. + * + * param base SPC peripheral base address. + * param driveStrength Specify the drive strength of CORE LDO Regulator in Active mode, please + refer to @ref spc_core_ldo_drive_strength_t. + * + * retval #kStatus_Success Set Core LDO regulator drive strength in Active power mode successful. + * retval #kStatus_SPC_CORELDOLowDriveStrengthIgnore If any voltage detect enabled, + core_ldo's drive strength can not set to low. + * retval #kStatus_SPC_BandgapModeWrong The selected bandgap mode is not allowed. + */ +status_t SPC_SetActiveModeCoreLDORegulatorDriveStrength(SPC_Type *base, spc_core_ldo_drive_strength_t driveStrength) +{ + if (driveStrength == kSPC_CoreLDO_LowDriveStrength) + { + /* If any voltage detect feature is enabled in Active mode, then CORE_LDO's drive strength must not set to low. + */ + if (SPC_GetActiveModeVoltageDetectStatus(base) != 0UL) + { + return kStatus_SPC_CORELDOLowDriveStrengthIgnore; + } + } + + if (driveStrength == kSPC_CoreLDO_NormalDriveStrength) + { + /* If specify normal drive strength, bandgap must not be disabled. */ + if (SPC_GetActiveModeBandgapMode(base) == kSPC_BandgapDisabled) + { + return kStatus_SPC_BandgapModeWrong; + } + } + + base->ACTIVE_CFG = + ((base->ACTIVE_CFG & ~SPC_ACTIVE_CFG_CORELDO_VDD_DS_MASK) | SPC_ACTIVE_CFG_CORELDO_VDD_DS(driveStrength)); + + return kStatus_Success; +} +#endif /* FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS */ + +/*! + * brief Configs CORE LDO Regulator in low power mode + * + * This function configs CORE LDO Regulator in Low Power mode. + * If CORE LDO VDD Drive Strength is set to Normal, the CORE LDO VDD regulator voltage + * level in Active mode must be equal to the voltage level in Low power mode. And the Bandgap + * must be programmed to select bandgap enabled. + * Core VDD voltage levels for the Core LDO low power regulator can only be changed when the CORE + * LDO Drive Strength is set as Normal. + * + * param base SPC peripheral base address. + * param option Pointer to the spc_lowpower_mode_Core_LDO_option_t structure. + * retval kStatus_Success Config Core LDO regulator in power mode successfully. + * retval kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * retval kStatus_SPC_CORELDOLowDriveStrengthIgnore HVDs/LVDs are not disabled before invoking this function. + * retval kStatus_SPC_BandgapModeWrong The bandgap is not enabled before invoking this function. + */ +status_t SPC_SetLowPowerModeCoreLDORegulatorConfig(SPC_Type *base, const spc_lowpower_mode_core_ldo_option_t *option) +{ + status_t status = kStatus_Success; + + if ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + /* + * $Line Coverage Justification$ + * $ref spc_c_ref_1$. + */ + return kStatus_SPC_Busy; + } + + status = SPC_SetLowPowerModeCoreLDORegulatorDriveStrength(base, option->CoreLDODriveStrength); + if (status == kStatus_Success) + { + (void)SPC_SetLowPowerModeCoreLDORegulatorVoltageLevel(base, option->CoreLDOVoltage); + } + + return status; +} + +/*! + * brief Set Core LDO VDD Regulator Voltage level in Low power mode. + * + * @note If Core LDO's drive strengths are same in active and low power mode, the Core LDO's voltage must be set to the + * same value in active and low power mode. Application should take care of this limitation. + * + * @note Some devices require Core LDO and DCDC have the same voltage level even if Core LDO is off. Application should + * take care of this limitation. + * + * param base SPC peripheral base address. + * param voltageLevel Voltage level of CORE LDO Regulator in Low power mode, please + refer to @ref spc_core_ldo_voltage_level_t. + * + * retval #kStatus_SPC_Busy The SPC instance is busy to execute other operation. + * retval #kStatus_Success Set Core LDO regulator voltage level in Low power mode successful. + */ +status_t SPC_SetLowPowerModeCoreLDORegulatorVoltageLevel(SPC_Type *base, spc_core_ldo_voltage_level_t voltageLevel) +{ + if ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + /* + * $Line Coverage Justification$ + * $ref spc_c_ref_1$. + */ + return kStatus_SPC_Busy; + } + + base->LP_CFG = ((base->LP_CFG & ~SPC_LP_CFG_CORELDO_VDD_LVL_MASK) | SPC_LP_CFG_CORELDO_VDD_LVL(voltageLevel)); + + /* + * $Branch Coverage Justification$ + * $ref spc_c_ref_1$. + */ + while ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + } + + return kStatus_Success; +} + +/*! + * brief Set Core LDO VDD Regulator Drive Strength in Low power mode. + * + * param base SPC peripheral base address. + * param driveStrength Specify drive strength of CORE LDO in low power mode. + * + * retval #kStatus_SPC_CORELDOLowDriveStrengthIgnore Some voltage detect enabled, CORE LDO's drive strength can not set + * as low. + * retval #kStatus_Success Set Core LDO regulator drive strength in Low power mode successful. + * retval #kStatus_SPC_BandgapModeWrong Bandgap is disabled when attempt to set CORE LDO work as normal drive strength. + */ +status_t SPC_SetLowPowerModeCoreLDORegulatorDriveStrength(SPC_Type *base, spc_core_ldo_drive_strength_t driveStrength) +{ + if (driveStrength == kSPC_CoreLDO_LowDriveStrength) + { + /* If any voltage detect feature is enabled in Low Power mode, then CORE_LDO's drive strength must not set to + * low. + */ + if (SPC_GetLowPowerModeVoltageDetectStatus(base) != 0UL) + { + return kStatus_SPC_CORELDOLowDriveStrengthIgnore; + } + } + else + { + /* To specify normal drive strength, the bandgap must be enabled in low power mode. */ + if (SPC_GetLowPowerModeBandgapMode(base) == kSPC_BandgapDisabled) + { + return kStatus_SPC_BandgapModeWrong; + } + } + + base->LP_CFG = ((base->LP_CFG & ~SPC_LP_CFG_CORELDO_VDD_DS_MASK) | SPC_LP_CFG_CORELDO_VDD_DS(driveStrength)); + + return kStatus_Success; +} + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) +/*! + * brief Configs System LDO VDD Regulator in Active mode. + * + * This function configs System LDO VDD Regulator in Active mode. + * If System LDO VDD Drive Strength is set to Normal, the Bandgap mode in Active mode must be programmed + * to a value that enable the bandgap. + * If any voltage detects are kept enabled, configuration to set System LDO VDD drive strength to low will + * be ignored. + * If select System LDO VDD Regulator voltage level to Over Drive Voltage, the Drive Strength of System LDO VDD + * Regulator must be set to Normal otherwise the regulator Drive Strength will be forced to Normal. + * If select System LDO VDD Regulator voltage level to Over Drive Voltage, the High voltage detect must be disabled. + * Otherwise it will be fail to regulator to Over Drive Voltage. + * + * param base SPC peripheral base address. + * param option Pointer to the spc_active_mode_Sys_LDO_option_t structure. + * retval kStatus_Success Config System LDO regulator in Active power mode successful. + * retval kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * retval kStatus_SPC_BandgapModeWrong The bandgap is not enabled before invoking this function. + * retval kStatus_SPC_SYSLDOOverDriveVoltageFail HVD of System VDD is not disable before setting to Over Drive voltage. + * retval kStatus_SPC_SYSLDOLowDriveStrengthIgnore Set System LDO VDD regulator's driver strength to Low will be + * ignored. + */ +status_t SPC_SetActiveModeSystemLDORegulatorConfig(SPC_Type *base, const spc_active_mode_sys_ldo_option_t *option) +{ + assert(option != NULL); + + if ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + /* + * $Line Coverage Justification$ + * $ref spc_c_ref_1$. + */ + return kStatus_SPC_Busy; + } + + /* Check input parameters before setting registers. */ + /* 1. To set to low DS, all LVDs/HVDs must be disabled previously. */ + if ((SPC_GetActiveModeVoltageDetectStatus(base) != 0UL) && + (option->SysLDODriveStrength == kSPC_SysLDO_LowDriveStrength)) + { + return kStatus_SPC_SYSLDOLowDriveStrengthIgnore; + } + /* 2. If specify normal drive strength, bandgap must not be disabled. */ + if ((SPC_GetActiveModeBandgapMode(base) == kSPC_BandgapDisabled) && + (option->SysLDODriveStrength == kSPC_SysLDO_NormalDriveStrength)) + { + return kStatus_SPC_BandgapModeWrong; + } + + /* 3. Must disable system LDO high voltage detector before specifing overdrive voltage. */ + if ((option->SysLDOVoltage == kSPC_SysLDO_OverDriveVoltage) && + ((SPC_GetActiveModeVoltageDetectStatus(base) & SPC_ACTIVE_CFG_SYS_HVDE_MASK) != 0UL)) + { + return kStatus_SPC_SYSLDOOverDriveVoltageFail; + } + + (void)SPC_SetActiveModeSystemLDORegulatorDriveStrength(base, option->SysLDODriveStrength); + (void)SPC_SetActiveModeSystemLDORegulatorVoltageLevel(base, option->SysLDOVoltage); + + return kStatus_Success; +} + +/*! + * brief Set System LDO Regulator voltage level in Active mode. + * + * @note The system LDO regulator can only operate at the overdrive voltage level for a limited amount of time for the + * life of chip. + * + * param base SPC peripheral base address. + * param voltageLevel Specify the voltage level of System LDO Regulator in Active mode. + * + * retval #kStatus_Success Set System LDO Regulator voltage level in Active mode successfully. + * retval #kStatus_SPC_SYSLDOOverDriveVoltageFail Must disable system LDO high voltage detector before specifing + * overdrive voltage. + */ +status_t SPC_SetActiveModeSystemLDORegulatorVoltageLevel(SPC_Type *base, spc_sys_ldo_voltage_level_t voltageLevel) +{ + if (voltageLevel == kSPC_SysLDO_OverDriveVoltage) + { + /* Must disable system LDO high voltage detector before specifing overdrive voltage. */ + if ((SPC_GetActiveModeVoltageDetectStatus(base) & SPC_ACTIVE_CFG_SYS_HVDE_MASK) != 0UL) + { + return kStatus_SPC_SYSLDOOverDriveVoltageFail; + } + } + + base->ACTIVE_CFG = + (base->ACTIVE_CFG & ~SPC_ACTIVE_CFG_SYSLDO_VDD_LVL_MASK) | SPC_ACTIVE_CFG_SYSLDO_VDD_LVL(voltageLevel); + + return kStatus_Success; +} + +/*! + * brief Set System LDO Regulator Drive Strength in Active mode. + * + * param base SPC peripheral base address. + * param driveStrength Specify the drive strength of System LDO Regulator in Active mode. + * + * retval #kStatus_Success Set System LDO Regulator drive strength in Active mode successfully. + * retval #kStatus_SPC_SYSLDOLowDriveStrengthIgnore Attempt to specify low drive strength is ignored due to any + voltage detect feature is enabled in active mode. + * retval #kStatus_SPC_BandgapModeWrong Bandgap mode in Active mode must be programmed to a value that enables + the bandgap if attempt to specify normal drive strength. + */ +status_t SPC_SetActiveModeSystemLDORegulatorDriveStrength(SPC_Type *base, spc_sys_ldo_drive_strength_t driveStrength) +{ + if (driveStrength == kSPC_SysLDO_LowDriveStrength) + { + /* If enabled any LVDs or HVDs, SPC will ignore the attempt to specify low drive strength. */ + if (SPC_GetActiveModeVoltageDetectStatus(base) != 0UL) + { + return kStatus_SPC_SYSLDOLowDriveStrengthIgnore; + } + } + + if (driveStrength == kSPC_SysLDO_NormalDriveStrength) + { + /* If specify normal drive strength, bandgap must not be disabled. */ + if (SPC_GetActiveModeBandgapMode(base) == kSPC_BandgapDisabled) + { + return kStatus_SPC_BandgapModeWrong; + } + } + + base->ACTIVE_CFG = + (base->ACTIVE_CFG & ~SPC_ACTIVE_CFG_SYSLDO_VDD_DS_MASK) | SPC_ACTIVE_CFG_SYSLDO_VDD_DS(driveStrength); + + return kStatus_Success; +} + +/*! + * brief Configs System LDO regulator in low power modes. + * + * This function configs System LDO regulator in low power modes. + * If System LDO VDD Regulator Drive strength is set to normal, bandgap mode in low power + * mode must be programmed to a value that enables the Bandgap. + * If any High voltage detectors or Low Voltage detectors are kept enabled, configuration + * to set System LDO Regulator drive strength as Low will be ignored. + * + * param base SPC peripheral base address. + * param option Pointer to spc_lowpower_mode_Sys_LDO_option_t structure. + * + * retval kStatus_Success Config System LDO regulator in Low Power Mode successfully. + * retval kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * retval kStatus_SPC_BandgapModeWrong The bandgap mode setting in Low Power Mode is wrong. + * retval kStatus_SPC_SYSLDOLowDriveStrengthIgnore Set driver strength to low will be ignored. + */ +status_t SPC_SetLowPowerModeSystemLDORegulatorConfig(SPC_Type *base, const spc_lowpower_mode_sys_ldo_option_t *option) +{ + status_t status; + + if ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + /* + * $Line Coverage Justification$ + * $ref spc_c_ref_1$. + */ + return kStatus_SPC_Busy; + } + + status = SPC_SetLowPowerModeSystemLDORegulatorDriveStrength(base, option->SysLDODriveStrength); + + return status; +} + +/*! + * brief Set System LDO Regulator drive strength in Low Power Mode. + * + * param base SPC peripheral base address. + * param driveStrength Specify the drive strength of System LDO Regulator in Low Power Mode. + * + * retval #kStatus_Success Set System LDO Regulator drive strength in Low Power Mode successfully. + * retval #kStatus_SPC_SYSLDOLowDriveStrengthIgnore Attempt to specify low drive strength is ignored due to any + voltage detect feature is enabled in low power mode. + * retval #kStatus_SPC_BandgapModeWrong Bandgap mode in low power mode must be programmed to a value that enables + the bandgap if attempt to specify normal drive strength. + */ +status_t SPC_SetLowPowerModeSystemLDORegulatorDriveStrength(SPC_Type *base, spc_sys_ldo_drive_strength_t driveStrength) +{ + if (driveStrength == kSPC_SysLDO_LowDriveStrength) + { + /* If enabled any LVDs or HVDs, SPC will ignore the attempt to specify low drive strength. */ + if (SPC_GetLowPowerModeVoltageDetectStatus(base) != 0UL) + { + return kStatus_SPC_SYSLDOLowDriveStrengthIgnore; + } + } + else + { + /* If specify normal drive strength, bandgap must not be disabled. */ + if (SPC_GetLowPowerModeBandgapMode(base) == kSPC_BandgapDisabled) + { + return kStatus_SPC_BandgapModeWrong; + } + } + + base->LP_CFG = (base->LP_CFG & ~SPC_LP_CFG_SYSLDO_VDD_DS_MASK) | SPC_LP_CFG_SYSLDO_VDD_DS(driveStrength); + + return kStatus_Success; +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) +/*! + * brief Configs DCDC VDD Regulator in Active mode. + * + * note When changing the DCDC output voltage level, take care to change the CORE LDO voltage level. + * + * param base SPC peripheral base address. + * param option Pointer to the spc_active_mode_DCDC_option_t structure. + * + * retval kStatus_Success Config DCDC regulator in Active power mode successful. + * retval kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * retval kStatus_SPC_BandgapModeWrong The bandgap mode setting in Active mode is wrong. + */ +status_t SPC_SetActiveModeDCDCRegulatorConfig(SPC_Type *base, const spc_active_mode_dcdc_option_t *option) +{ + assert(option != NULL); + status_t status = kStatus_Success; + + if ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + /* + * $Line Coverage Justification$ + * $ref spc_c_ref_1$. + */ + return kStatus_SPC_Busy; + } + + status = SPC_SetActiveModeDCDCRegulatorDriveStrength(base, option->DCDCDriveStrength); + + if (status == kStatus_Success) + { + SPC_SetActiveModeDCDCRegulatorVoltageLevel(base, option->DCDCVoltage); + } + + /* + * $Branch Coverage Justification$ + * $ref spc_c_ref_1$. + */ + while ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + } + + return status; +} + +/*! + * brief Set DCDC VDD Regulator drive strength in Active mode. + * + * note To set DCDC drive strength as Normal, the bandgap must be enabled. + * + * param base SPC peripheral base address. + * param driveStrength Specify the DCDC VDD regulator drive strength, please refer to @ref spc_dcdc_drive_strength_t. + * + * retval #kStatus_Success Set DCDC VDD Regulator drive strength in Active mode successfully. + * retval #kStatus_SPC_BandgapModeWrong Set DCDC VDD Regulator drive strength to Normal, the Bandgap must be enabled. + */ +status_t SPC_SetActiveModeDCDCRegulatorDriveStrength(SPC_Type *base, spc_dcdc_drive_strength_t driveStrength) +{ + if (driveStrength == kSPC_DCDC_NormalDriveStrength) + { + /* If specify normal drive strength, bandgap must not be disabled. */ + if (SPC_GetActiveModeBandgapMode(base) == kSPC_BandgapDisabled) + { + return kStatus_SPC_BandgapModeWrong; + } + } + + base->ACTIVE_CFG = + ((base->ACTIVE_CFG) & (~SPC_ACTIVE_CFG_DCDC_VDD_DS_MASK)) | SPC_ACTIVE_CFG_DCDC_VDD_DS(driveStrength); + + return kStatus_Success; +} + +/*! + * brief Configs DCDC VDD Regulator in Low power modes. + * + * If DCDC VDD Drive Strength is set to Normal, the Bandgap mode in Low Power mode must be programmed + * to a value that enables the Bandgap. + * In Deep Power Down mode, DCDC regulator is always turned off. + * + * param base SPC peripheral base address. + * param option Pointer to the spc_lowpower_mode_DCDC_option_t structure. + * + * retval kStatus_Success Config DCDC regulator in low power mode successfully. + * retval kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * retval kStatus_SPC_BandgapModeWrong The bandgap should be enabled before invoking this function. + */ +status_t SPC_SetLowPowerModeDCDCRegulatorConfig(SPC_Type *base, const spc_lowpower_mode_dcdc_option_t *option) +{ + if ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + /* + * $Line Coverage Justification$ + * $ref spc_c_ref_1$. + */ + return kStatus_SPC_Busy; + } + + /* Check input parameter before setting registers. */ + if ((option->DCDCDriveStrength == kSPC_DCDC_NormalDriveStrength) && + (SPC_GetLowPowerModeBandgapMode(base) == kSPC_BandgapDisabled)) + { + return kStatus_SPC_BandgapModeWrong; + } + + /* + 1. Configure to desired voltage level. + 2. Change to low drive strength. + 3. Configure same voltage level in active mode. + */ + SPC_SetLowPowerModeDCDCRegulatorVoltageLevel(base, option->DCDCVoltage); + + /* Change to desired drive strength. */ + if (option->DCDCDriveStrength != kSPC_DCDC_LowDriveStrength) + { + (void)SPC_SetLowPowerModeDCDCRegulatorDriveStrength(base, option->DCDCDriveStrength); + } + + /* + * $Branch Coverage Justification$ + * $ref spc_c_ref_1$. + */ + while ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + } + + return kStatus_Success; +} + +/*! + * brief Set DCDC VDD Regulator drive strength in Low power mode. + * + * param base SPC peripheral base address. + * param driveStrength Specify the DCDC VDD Regulator drive strength, please refer to @ref spc_dcdc_drive_strength_t. + * + * retval #kStatus_Success Set DCDC VDD Regulator drive strength in Low power mode successfully. + * retval #kStatus_SPC_BandgapModeWrong Set DCDC VDD Regulator drive strength to Normal, the Bandgap must be enabled. + */ +status_t SPC_SetLowPowerModeDCDCRegulatorDriveStrength(SPC_Type *base, spc_dcdc_drive_strength_t driveStrength) +{ + if (driveStrength == kSPC_DCDC_NormalDriveStrength) + { + /* If specify normal drive strength, bandgap must not be disabled. */ + if (SPC_GetLowPowerModeBandgapMode(base) == kSPC_BandgapDisabled) + { + return kStatus_SPC_BandgapModeWrong; + } + } + + base->LP_CFG = ((base->LP_CFG) & (~SPC_LP_CFG_DCDC_VDD_DS_MASK)) | SPC_LP_CFG_DCDC_VDD_DS(driveStrength); + + return kStatus_Success; +} + +/*! + * brief Config DCDC Burst options + * + * param base SPC peripheral base address. + * param config Pointer to spc_DCDC_burst_config_t structure. + */ +void SPC_SetDCDCBurstConfig(SPC_Type *base, spc_dcdc_burst_config_t *config) +{ + assert(config != NULL); + uint32_t reg; + reg = base->DCDC_CFG; + reg &= ~(SPC_DCDC_CFG_FREQ_CNTRL_MASK | SPC_DCDC_CFG_FREQ_CNTRL_ON_MASK); + reg |= SPC_DCDC_CFG_FREQ_CNTRL(config->freq); + reg |= config->stabilizeBurstFreq ? SPC_DCDC_CFG_FREQ_CNTRL_ON(1U) : SPC_DCDC_CFG_FREQ_CNTRL_ON(0U); + base->DCDC_CFG = reg; + + /* Blocking until previous DCDC burst completed. */ + while ((base->DCDC_BURST_CFG & SPC_DCDC_BURST_CFG_BURST_ACK_MASK) == 0UL) + { + } + + if ((config->sofwareBurstRequest) || (config->externalBurstRequest)) + { + /* Clear DCDC burst acknowledge flag. */ + base->DCDC_BURST_CFG |= SPC_DCDC_BURST_CFG_BURST_ACK_MASK; + } + base->DCDC_BURST_CFG |= SPC_DCDC_BURST_CFG_EXT_BURST_EN(config->externalBurstRequest); + + if (config->sofwareBurstRequest) + { + base->DCDC_BURST_CFG |= SPC_DCDC_BURST_CFG_BURST_REQ_MASK; + } +} + +/*! + * brief Set the count value of the reference clock. + * + * This function set the count value of the reference clock to control the frequency + * of dcdc refresh when dcdc is configured in Pulse Refresh mode. + * + * param base SPC peripheral base address. + * param count The count value, 16 bit width. + */ +void SPC_SetDCDCRefreshCount(SPC_Type *base, uint16_t count) +{ + uint32_t reg; + + reg = base->DCDC_BURST_CFG; + reg &= ~SPC_DCDC_BURST_CFG_PULSE_REFRESH_CNT_MASK; + reg |= SPC_DCDC_BURST_CFG_PULSE_REFRESH_CNT(count); + + base->DCDC_BURST_CFG = reg; +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + +/*! + * brief Configs all settings of regulators in Active mode at a time. + * + * @note This function is used to overwrite all settings of regulators(including bandgap mode, regulators' + * drive strength and voltage level) in active mode at a time. + * + * @note Enable/disable LVDs/HVDs before invoking this function. + * + * @note This function will check input parameters based on hardware restrictions before setting registers, if input + * parameters do not satisfy hardware restrictions the specific error will be reported. + * + * + * @note Some hardware restrictions not covered, application should be aware of this and follow this hardware + * restrictions otherwise some unkown issue may occur: + * 1. If Core LDO's drive strength are set to same value in both Active mode and low power mode, + * the voltage level should also set to same value. + * 2. When switching Core LDO's drive strength from low to normal, ensure the LDO_CORE high voltage level is set + * to same level that was set prior to switching to the LDO_CORE drive strength. Otherwise, if the LVDs are + * enabled, an unexpected LVD can occur. + * + * @note If this function can not satisfy some tricky settings, please invoke other low-level functions. + * + * param base SPC peripheral base address. + * param config Pointer to spc_active_mode_regulators_config_t structure. + * retval kStatus_Success Config regulators in Active power mode successful. + * retval kStatus_SPC_BandgapModeWrong The bandgap mode setting in Active mode is wrong. + * retval kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * retval kStatus_SPC_CORELDOVoltageWrong The selected voltage level in active mode is not allowed. + * retval kStatus_SPC_SYSLDOOverDriveVoltageFail Fail to regulator to Over Drive Voltage. + * retval kStatus_SPC_SYSLDOLowDriveStrengthIgnore Set driver strength to Low will be ignored. + * retval kStatus_SPC_DCDCLowDriveStrengthIgnore Set driver strength to Low will be ignored. + */ +status_t SPC_SetActiveModeRegulatorsConfig(SPC_Type *base, const spc_active_mode_regulators_config_t *config) +{ + assert(config != NULL); + + uint32_t activeModeVDValue = SPC_GetActiveModeVoltageDetectStatus(base); + + /* Check input parameters */ + /* 1. Bandgap should not be disabled if any of regulator in normal drive strength or + if any of LVDs/HVDs are enabled or if VDD CORE glitch detect are enabled. */ + if ((config->bandgapMode == kSPC_BandgapDisabled) && + ((activeModeVDValue != 0UL) +#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) + || (SPC_CheckActiveModeVddCoreGlitchDetectEnabled(base) == true) +#endif /* FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT */ +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) + || (config->DCDCOption.DCDCDriveStrength == kSPC_DCDC_NormalDriveStrength) +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + || (config->SysLDOOption.SysLDODriveStrength == kSPC_SysLDO_NormalDriveStrength) +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ +#if (defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) + || (config->CoreLDOOption.CoreLDODriveStrength == kSPC_CoreLDO_NormalDriveStrength) +#endif /* FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS */ + )) + { + return kStatus_SPC_BandgapModeWrong; + } + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + /* 2. Must disable system LDO high voltage detector before specifing SysLDO to overdrive voltage */ + if (((activeModeVDValue & SPC_ACTIVE_CFG_SYS_HVDE_MASK) != 0UL) && + (config->SysLDOOption.SysLDOVoltage == kSPC_SysLDO_OverDriveVoltage)) + { + return kStatus_SPC_SYSLDOOverDriveVoltageFail; + } +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + /* 3. To set System LDO's drive strength to low, all LVDs and HVDs must be disabled. */ + if ((activeModeVDValue != 0UL) && (config->SysLDOOption.SysLDODriveStrength == kSPC_SysLDO_LowDriveStrength)) + { + return kStatus_SPC_SYSLDOLowDriveStrengthIgnore; + } +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + +#if (defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) + /* 4. To set Core LDO's drive strength to low, all LVDs and HVDs must be disabled. */ + if ((activeModeVDValue != 0UL) && (config->CoreLDOOption.CoreLDODriveStrength == kSPC_CoreLDO_LowDriveStrength)) + { + return kStatus_SPC_CORELDOLowDriveStrengthIgnore; + } +#endif /* FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) + /* 5. Core LDO and DCDC should have same voltage level. */ + if ((uint8_t)config->DCDCOption.DCDCVoltage != (uint8_t)config->CoreLDOOption.CoreLDOVoltage) + { + return kStatus_SPC_CORELDOVoltageWrong; + } +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + + if ((base->SC & SPC_SC_BUSY_MASK) != 0UL) + { + return kStatus_SPC_Busy; + } + + base->ACTIVE_CFG = + ((base->ACTIVE_CFG) & ~(SPC_ACTIVE_CFG_BGMODE_MASK)) | SPC_ACTIVE_CFG_BGMODE(config->bandgapMode); +#if (defined(FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) && FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) + SPC_EnableActiveModeCMPBandgapBuffer(base, config->lpBuff); +#endif /* FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + (void)SPC_SetActiveModeSystemLDORegulatorConfig(base, &config->SysLDOOption); +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) + (void)SPC_SetActiveModeDCDCRegulatorConfig(base, &config->DCDCOption); +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + + (void)SPC_SetActiveModeCoreLDORegulatorConfig(base, &config->CoreLDOOption); + + return kStatus_Success; +} + +/*! + * brief Configs regulators in Low Power mode. + * + * This function provides the method to config all on-chip regulators in Low Power mode. + * + * param base SPC peripheral base address. + * param config Pointer to spc_lowpower_mode_regulators_config_t structure. + * retval #kStatus_Success Config regulators in Low power mode successful. + * retval #kStatus_SPC_BandgapModeWrong The bandgap should not be disabled based on input settings. + * retval #kStatus_SPC_CORELDOLowDriveStrengthIgnore Set driver strength to low will be ignored. + * retval #kStatus_SPC_SYSLDOLowDriveStrengthIgnore Set driver strength to low will be ignored. + * retval #kStatus_SPC_CORELDOVoltageWrong Core LDO and System LDO do not have same voltage level. + */ +status_t SPC_SetLowPowerModeRegulatorsConfig(SPC_Type *base, const spc_lowpower_mode_regulators_config_t *config) +{ + assert(config != NULL); + uint32_t lpModeVDValue = SPC_GetLowPowerModeVoltageDetectStatus(base); + + /* Check input parameters */ + /* 1. Bandgap should not be disabled if any of regulator in normal drive strength or + if any of LVDs/HVDs are enabled or if VDD CORE glitch detect are enabled. */ + if ((config->bandgapMode == kSPC_BandgapDisabled) && + ((lpModeVDValue != 0UL) +#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) + || (SPC_CheckLowPowerModeVddCoreGlitchDetectEnabled(base) == true) +#endif /* FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT */ +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) + || (config->DCDCOption.DCDCDriveStrength == kSPC_DCDC_NormalDriveStrength) +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + || (config->SysLDOOption.SysLDODriveStrength == kSPC_SysLDO_NormalDriveStrength) +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ +#if (defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) + || (config->CoreLDOOption.CoreLDODriveStrength == kSPC_CoreLDO_NormalDriveStrength) +#endif /* FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS */ + )) + { + return kStatus_SPC_BandgapModeWrong; + } + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + /* 2. To set System LDO's drive strength to low, all LVDs and HVDs must be disabled. */ + if ((lpModeVDValue != 0UL) && (config->SysLDOOption.SysLDODriveStrength == kSPC_SysLDO_LowDriveStrength)) + { + return kStatus_SPC_SYSLDOLowDriveStrengthIgnore; + } +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + +#if (defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) + /* 3. To set Core LDO's drive strength to low, all LVDs and HVDs must be disabled. */ + if ((lpModeVDValue != 0UL) && (config->CoreLDOOption.CoreLDODriveStrength == kSPC_CoreLDO_LowDriveStrength)) + { + return kStatus_SPC_CORELDOLowDriveStrengthIgnore; + } +#endif /* FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) + /* 5. Core LDO and DCDC should have same voltage level. */ + if ((uint8_t)config->DCDCOption.DCDCVoltage != (uint8_t)config->CoreLDOOption.CoreLDOVoltage) + { + return kStatus_SPC_CORELDOVoltageWrong; + } +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + base->LP_CFG = ((base->LP_CFG) & ~(SPC_LP_CFG_BGMODE_MASK)) | SPC_LP_CFG_BGMODE(config->bandgapMode); +#if (defined(FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) && FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) + SPC_EnableLowPowerModeCMPBandgapBuffer(base, config->lpBuff); +#endif /* FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT */ +#if (defined(FSL_FEATURE_MCX_SPC_HAS_COREVDD_IVS_EN_BIT) && FSL_FEATURE_MCX_SPC_HAS_COREVDD_IVS_EN_BIT) + SPC_EnableLowPowerModeCoreVDDInternalVoltageScaling(base, config->CoreIVS); +#endif /* FSL_FEATURE_MCX_SPC_HAS_COREVDD_IVS_EN_BIT */ + SPC_EnableLowPowerModeLowPowerIREF(base, config->lpIREF); + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + (void)SPC_SetLowPowerModeSystemLDORegulatorConfig(base, &config->SysLDOOption); +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) + (void)SPC_SetLowPowerModeDCDCRegulatorConfig(base, &config->DCDCOption); +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + + (void)SPC_SetLowPowerModeCoreLDORegulatorConfig(base, &config->CoreLDOOption); + + return kStatus_Success; +} diff --git a/hw/bsp/mcx/drivers/spc/fsl_spc.h b/hw/bsp/mcx/drivers/spc/fsl_spc.h new file mode 100644 index 000000000..52cb71c24 --- /dev/null +++ b/hw/bsp/mcx/drivers/spc/fsl_spc.h @@ -0,0 +1,2433 @@ +/* + * Copyright 2022-2024 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FSL_SPC_H_ +#define FSL_SPC_H_ +#include "fsl_common.h" + +/*! + * @addtogroup mcx_spc + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @name Driver version */ +/*! @{ */ +/*! @brief SPC driver version 2.4.2. */ +#define FSL_SPC_DRIVER_VERSION (MAKE_VERSION(2, 4, 2)) +/*! @} */ + +#define SPC_EVD_CFG_REG_EVDISO_SHIFT 0UL +#define SPC_EVD_CFG_REG_EVDLPISO_SHIFT 8UL +#define SPC_EVD_CFG_REG_EVDSTAT_SHIFT 16UL + +#define SPC_EVD_CFG_REG_EVDISO(x) ((uint32_t)(x) << SPC_EVD_CFG_REG_EVDISO_SHIFT) +#define SPC_EVD_CFG_REG_EVDLPISO(x) ((uint32_t)(x) << SPC_EVD_CFG_REG_EVDLPISO_SHIFT) +#define SPC_EVD_CFG_REG_EVDSTAT(x) ((uint32_t)(x) << SPC_EVD_CFG_REG_EVDSTAT_SHIFT) + +#if (defined(SPC_GLITCH_DETECT_SC_CNT_SELECT_MASK)) +#define VDD_CORE_GLITCH_DETECT_SC GLITCH_DETECT_SC +#define SPC_VDD_CORE_GLITCH_DETECT_SC_GLITCH_DETECT_FLAG_MASK SPC_GLITCH_DETECT_SC_GLITCH_DETECT_FLAG_MASK +#define SPC_VDD_CORE_GLITCH_DETECT_SC_GLITCH_DETECT_FLAG SPC_GLITCH_DETECT_SC_GLITCH_DETECT_FLAG +#define SPC_VDD_CORE_GLITCH_DETECT_SC_LOCK_MASK SPC_GLITCH_DETECT_SC_LOCK_MASK +#define SPC_VDD_CORE_GLITCH_DETECT_SC_CNT_SELECT_MASK SPC_GLITCH_DETECT_SC_CNT_SELECT_MASK +#define SPC_VDD_CORE_GLITCH_DETECT_SC_CNT_SELECT SPC_GLITCH_DETECT_SC_CNT_SELECT +#define SPC_VDD_CORE_GLITCH_DETECT_SC_RE_MASK SPC_GLITCH_DETECT_SC_RE_MASK +#define SPC_VDD_CORE_GLITCH_DETECT_SC_RE SPC_GLITCH_DETECT_SC_RE +#define SPC_VDD_CORE_GLITCH_DETECT_SC_TIMEOUT_MASK SPC_GLITCH_DETECT_SC_TIMEOUT_MASK +#define SPC_VDD_CORE_GLITCH_DETECT_SC_TIMEOUT SPC_GLITCH_DETECT_SC_TIMEOUT +#define SPC_VDD_CORE_GLITCH_DETECT_SC_IE_MASK SPC_GLITCH_DETECT_SC_IE_MASK +#define SPC_VDD_CORE_GLITCH_DETECT_SC_IE SPC_GLITCH_DETECT_SC_IE +#endif + +/*! + * @brief SPC status enumeration. + * + * @note Some device(such as MCXA family) do not equip DCDC or System LDO, please refer to the reference manual + * to check. + */ +enum +{ + kStatus_SPC_Busy = MAKE_STATUS(kStatusGroup_SPC, 0U), /*!< The SPC instance is busy executing any + type of power mode transition. */ +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) + kStatus_SPC_DCDCLowDriveStrengthIgnore = MAKE_STATUS(kStatusGroup_SPC, 1U), /*!< DCDC Low drive strength setting be + ignored for LVD/HVD enabled. */ + kStatus_SPC_DCDCPulseRefreshModeIgnore = MAKE_STATUS(kStatusGroup_SPC, 2U), /*!< DCDC Pulse Refresh Mode drive + strength setting be ignored for LVD/HVD enabled. */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + kStatus_SPC_SYSLDOOverDriveVoltageFail = MAKE_STATUS(kStatusGroup_SPC, 3U), /*!< SYS LDO regulate to Over drive + voltage failed for SYS LDO HVD must be disabled. */ + kStatus_SPC_SYSLDOLowDriveStrengthIgnore = MAKE_STATUS(kStatusGroup_SPC, 4U), /*!< SYS LDO Low driver strength + setting be ignored for LDO LVD/HVD enabled. */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + kStatus_SPC_CORELDOLowDriveStrengthIgnore = MAKE_STATUS(kStatusGroup_SPC, 5U), /*!< CORE LDO Low driver strength + setting be ignored for LDO LVD/HVD enabled. */ + kStatus_SPC_CORELDOVoltageWrong = MAKE_STATUS(kStatusGroup_SPC, 7U), /*!< Core LDO voltage is wrong. */ + kStatus_SPC_CORELDOVoltageSetFail = MAKE_STATUS(kStatusGroup_SPC, 8U), /*!< Core LDO voltage set fail. */ + kStatus_SPC_BandgapModeWrong = MAKE_STATUS(kStatusGroup_SPC, 6U), /*!< Selected Bandgap Mode wrong. */ +}; + +/*! + * @brief Voltage Detect Status Flags. + */ +enum _spc_voltage_detect_flags +{ +#if (defined(FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) && FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) + kSPC_IOVDDHighVoltageDetectFlag = SPC_VD_STAT_IOVDD_HVDF_MASK, /*!< IO VDD High-Voltage detect flag. */ + kSPC_IOVDDLowVoltageDetectFlag = SPC_VD_STAT_IOVDD_LVDF_MASK, /*!< IO VDD Low-Voltage detect flag. */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD */ + kSPC_SystemVDDHighVoltageDetectFlag = SPC_VD_STAT_SYSVDD_HVDF_MASK, /*!< System VDD High-Voltage detect flag. */ + kSPC_SystemVDDLowVoltageDetectFlag = SPC_VD_STAT_SYSVDD_LVDF_MASK, /*!< System VDD Low-Voltage detect flag. */ +#if (defined(FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) && FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) + kSPC_CoreVDDHighVoltageDetectFlag = SPC_VD_STAT_COREVDD_HVDF_MASK, /*!< Core VDD High-Voltage detect flag. */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD */ + kSPC_CoreVDDLowVoltageDetectFlag = SPC_VD_STAT_COREVDD_LVDF_MASK, /*!< Core VDD Low-Voltage detect flag. */ +}; + +/*! + * @brief SPC power domain isolation status. + * @note Some devices(such as MCXA family) do not contain WAKE Power Domain, please refer to the reference manual to + * check. + */ +enum _spc_power_domains +{ + kSPC_MAINPowerDomainRetain = 1UL << 16U, /*!< Peripherals and IO pads retain in MAIN Power Domain. */ + kSPC_WAKEPowerDomainRetain = 1UL << 17U, /*!< Peripherals and IO pads retain in WAKE Power Domain. */ +}; + +/*! + * @brief The enumeration of all analog module that can be controlled by SPC in active or low-power modes. + * @anchor spc_analog_module_control + */ +enum _spc_analog_module_control +{ + kSPC_controlVref = 1UL << 0UL, /*!< Enable/disable VREF in active or low-power modes. */ + kSPC_controlUsb3vDet = 1UL << 1UL, /*!< Enable/disable USB3V_Det in active or low-power modes. */ + kSPC_controlDac0 = 1UL << 4UL, /*!< Enable/disable DAC0 in active or low-power modes. */ + kSPC_controlDac1 = 1UL << 5UL, /*!< Enable/disable DAC1 in active or low-power modes. */ + kSPC_controlDac2 = 1UL << 6UL, /*!< Enable/disable DAC2 in active or low-power modes. */ + kSPC_controlOpamp0 = 1UL << 8UL, /*!< Enable/disable OPAMP0 in active or low-power modes. */ + kSPC_controlOpamp1 = 1UL << 9UL, /*!< Enable/disable OPAMP1 in active or low-power modes. */ + kSPC_controlOpamp2 = 1UL << 10UL, /*!< Enable/disable OPAMP2 in active or low-power modes. */ + kSPC_controlCmp0 = 1UL << 16UL, /*!< Enable/disable CMP0 in active or low-power modes. */ + kSPC_controlCmp1 = 1UL << 17UL, /*!< Enable/disable CMP1 in active or low-power modes. */ + kSPC_controlCmp2 = 1UL << 18UL, /*!< Enable/disable CMP2 in active or low-power modes. */ + kSPC_controlCmp0Dac = 1UL << 20UL, /*!< Enable/disable CMP0_DAC in active or low-power modes. */ + kSPC_controlCmp1Dac = 1UL << 21UL, /*!< Enable/disable CMP1_DAC in active or low-power modes. */ + kSPC_controlCmp2Dac = 1UL << 22UL, /*!< Enable/disable CMP2_DAC in active or low-power modes. */ + kSPC_controlAllModules = 0x770773UL, /*!< Enable/disable all modules in active or low-power modes. */ +}; + +/*! + * @brief The enumeration of spc power domain, the connected power domain is chip specfic, please refer to chip's RM + * for details. + */ +typedef enum _spc_power_domain_id +{ + kSPC_PowerDomain0 = 0U, /*!< Power domain0, the connected power domain is chip specific. */ + kSPC_PowerDomain1 = 1U, /*!< Power domain1, the connected power domain is chip specific. */ +} spc_power_domain_id_t; + +/*! + * @brief The enumeration of Power domain's low power mode. + */ +typedef enum _spc_power_domain_low_power_mode +{ + kSPC_SleepWithSYSClockRunning = 0U, /*!< Power domain request SLEEP mode with SYS clock running. */ + kSPC_DeepSleepWithSysClockOff = 1U, /*!< Power domain request deep sleep mode with system clock off. */ + kSPC_PowerDownWithSysClockOff = 2U, /*!< Power domain request power down mode with system clock off. */ + kSPC_DeepPowerDownWithSysClockOff = 4U, /*!< Power domain request deep power down mode with system clock off. */ +} spc_power_domain_low_power_mode_t; + +/*! + * @brief SPC low power request output pin polarity. + */ +typedef enum _spc_lowPower_request_pin_polarity +{ + kSPC_HighTruePolarity = 0x0U, /*!< Control the High Polarity of the Low Power Reqest Pin. */ + kSPC_LowTruePolarity = 0x1U, /*!< Control the Low Polarity of the Low Power Reqest Pin. */ +} spc_lowpower_request_pin_polarity_t; + +/*! + * @brief SPC low power request output override. + */ +typedef enum _spc_lowPower_request_output_override +{ + kSPC_LowPowerRequestNotForced = 0x0U, /*!< Not Forced. */ + kSPC_LowPowerRequestReserved = 0x1U, /*!< Reserved. */ + kSPC_LowPowerRequestForcedLow = 0x2U, /*!< Forced Low (Ignore LowPower request output polarity setting.) */ + kSPC_LowPowerRequestForcedHigh = 0x3U, /*!< Forced High (Ignore LowPower request output polarity setting.) */ +} spc_lowpower_request_output_override_t; + +/*! + * @brief SPC Bandgap mode enumeration in Active mode or Low Power mode. + */ +typedef enum _spc_bandgap_mode +{ + kSPC_BandgapDisabled = 0x0U, /*!< Bandgap disabled. */ + kSPC_BandgapEnabledBufferDisabled = 0x1U, /*!< Bandgap enabled with Buffer disabled. */ + kSPC_BandgapEnabledBufferEnabled = 0x2U, /*!< Bandgap enabled with Buffer enabled. */ + kSPC_BandgapReserved = 0x3U, /*!< Reserved. */ +} spc_bandgap_mode_t; + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) +/*! + * @brief DCDC regulator voltage level enumeration in Active mode or Low Power Mode. + * + * @note #kSPC_DCDC_RetentionVoltage not supported for all power modes. + */ +typedef enum _spc_dcdc_voltage_level +{ + kSPC_DCDC_RetentionVoltage = 0x0U, /*!< DCDC_CORE Regulator regulate to retention + Voltage(Only supportedin low power modes) */ + kSPC_DCDC_MidVoltage = 0x1U, /*!< DCDC_CORE Regulator regulate to Mid Voltage(1.0V). */ + kSPC_DCDC_NormalVoltage = 0x2U, /*!< DCDC_CORE Regulator regulate to Normal Voltage(1.1V). */ + kSPC_DCDC_OverdriveVoltage = 0x3U, /*!< DCDC_CORE Regulator regulate to Safe-Mode Voltage(1.2V). */ +} spc_dcdc_voltage_level_t; + +/*! + * @brief DCDC regulator Drive Strength enumeration in Active mode or Low Power Mode. + * + * @note Different drive strength differ in these DCDC characterstics: + * Maximum load current + * Quiescent current + * Transient response. + */ +typedef enum _spc_dcdc_drive_strength +{ + kSPC_DCDC_PulseRefreshMode = 0x0U, /*!< DCDC_CORE Regulator Drive Strength set to Pulse Refresh Mode, + * This enum member is only useful for Low Power Mode config, please + * note that pluse refresh mode is invalid in SLEEP mode. + */ + kSPC_DCDC_LowDriveStrength = 0x1U, /*!< DCDC_CORE regulator Drive Strength set to low. */ + kSPC_DCDC_NormalDriveStrength = 0x2U, /*!< DCDC_CORE regulator Drive Strength set to Normal. */ +} spc_dcdc_drive_strength_t; +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) +/*! + * @brief SYS LDO regulator voltage level enumeration in Active mode. + */ +typedef enum _spc_sys_ldo_voltage_level +{ + kSPC_SysLDO_NormalVoltage = 0x0U, /*!< SYS LDO VDD Regulator regulate to Normal Voltage(1.8V). */ + kSPC_SysLDO_OverDriveVoltage = 0x1U, /*!< SYS LDO VDD Regulator regulate to Over Drive Voltage(2.5V). */ +} spc_sys_ldo_voltage_level_t; + +/*! + * @brief SYS LDO regulator Drive Strength enumeration in Active mode or Low Power mode. + */ +typedef enum _spc_sys_ldo_drive_strength +{ + kSPC_SysLDO_LowDriveStrength = 0x0U, /*!< SYS LDO VDD regulator Drive Strength set to low. */ + kSPC_SysLDO_NormalDriveStrength = 0x1U, /*!< SYS LDO VDD regulator Drive Strength set to Normal. */ +} spc_sys_ldo_drive_strength_t; +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + +/*! + * @brief Core LDO regulator voltage level enumeration in Active mode or Low Power mode. + */ +typedef enum _spc_core_ldo_voltage_level +{ + kSPC_CoreLDO_UnderDriveVoltage = 0x0U, /*!< @deprecated, to align with description of latest RM, please use + #kSPC_Core_LDO_RetentionVoltage as instead. */ + kSPC_Core_LDO_RetentionVoltage = 0x0U, /*!< Core LDO VDD regulator regulate to retention voltage, please note that + only useful in low power modes and not all devices support this options + please refer to devices' RM for details. */ + kSPC_CoreLDO_MidDriveVoltage = 0x1U, /*!< Core LDO VDD regulator regulate to Mid Drive Voltage. */ + kSPC_CoreLDO_NormalVoltage = 0x2U, /*!< Core LDO VDD regulator regulate to Normal Voltage. */ + kSPC_CoreLDO_OverDriveVoltage = 0x3U, /*!< Core LDO VDD regulator regulate to overdrive Voltage. */ +} spc_core_ldo_voltage_level_t; + +/*! + * @brief CORE LDO VDD regulator Drive Strength enumeration in Low Power mode. + */ +typedef enum _spc_core_ldo_drive_strength +{ + kSPC_CoreLDO_LowDriveStrength = 0x0U, /*!< Core LDO VDD regulator Drive Strength set to low. */ + kSPC_CoreLDO_NormalDriveStrength = 0x1U, /*!< Core LDO VDD regulator Drive Strength set to Normal. */ +} spc_core_ldo_drive_strength_t; + +/*! + * @brief IO VDD Low-Voltage Level Select. + */ +typedef enum _spc_low_voltage_level_select +{ + kSPC_LowVoltageNormalLevel = 0x0U, /*!< @deprecated, please use kSPC_LowVoltageHighRange as instead. */ + kSPC_LowVoltageSafeLevel = 0x1U, /*!< @deprecated, please use kSPC_LowVoltageLowRange as instead. */ + + kSPC_LowVoltageHighRange = 0x0U, /*!< High range LVD threshold. */ + kSPC_LowVoltageLowRange = 0x1U, /*!< Low range LVD threshold. */ +} spc_low_voltage_level_select_t; + +#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) +/*! + * @brief Used to select output of 4-bit ripple counter is used to monitor a glitch on VDD core. + */ +typedef enum _spc_vdd_core_glitch_ripple_counter_select +{ + kSPC_selectBit0Of4bitRippleCounter = 0x0U, /*!< Select bit-0 of 4-bit Ripple Counter + to detect glitch on VDD Core. */ + kSPC_selectBit1Of4bitRippleCounter = 0x1U, /*!< Select bit-1 of 4-bit Ripple Counter + to detect glitch on VDD Core. */ + kSPC_selectBit2Of4bitRippleCounter = 0x2U, /*!< Select bit-2 of 4-bit Ripple Counter + to detect glitch on VDD Core. */ + kSPC_selectBit3Of4bitRippleCounter = 0x3U, /*!< Select bit-3 of 4-bit Ripple Counter + to detect glitch on VDD Core. */ +} spc_vdd_core_glitch_ripple_counter_select_t; +#endif + +/*! + * @brief The list of the operating voltage for the SRAM's read/write timing margin. + */ +typedef enum _spc_sram_operate_voltage +{ + kSPC_sramOperateAt1P0V = 0x1U, /*!< SRAM configured for 1.0V operation. */ + kSPC_sramOperateAt1P1V = 0x2U, /*!< SRAM configured for 1.1V operation. */ + kSPC_sramOperateAt1P2V = 0x3U, /*!< SRAM configured for 1.2V operation. */ +} spc_sram_operate_voltage_t; + +#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) +/*! + * @brief The configuration of VDD Core glitch detector. + */ +typedef struct _spc_vdd_core_glitch_detector_config +{ + spc_vdd_core_glitch_ripple_counter_select_t rippleCounterSelect; /*!< Used to set ripple counter. */ + uint8_t resetTimeoutValue; /*!< The timeout value used to reset glitch detect/compare logic after an initial + glitch is detected. */ + bool enableReset; /*!< Used to enable/disable POR/LVD reset that caused by CORE VDD glitch detect error. */ + bool enableInterrupt; /*!< Used to enable/disable hardware interrupt if CORE VDD glitch detect error. */ +} spc_vdd_core_glitch_detector_config_t; +#endif + +typedef struct _spc_sram_voltage_config +{ + spc_sram_operate_voltage_t operateVoltage; /*!< Specifies the operating voltage for the SRAM's + read/write timing margin. */ + bool requestVoltageUpdate; /*!< Used to control whether request an SRAM trim value change. */ +} spc_sram_voltage_config_t; + +/*! + * @brief Low Power Request output pin configuration. + */ +typedef struct _spc_lowpower_request_config +{ + bool enable; /*!< Low Power Request Output enable. */ + spc_lowpower_request_pin_polarity_t polarity; /*!< Low Power Request Output pin polarity select. */ + spc_lowpower_request_output_override_t override; /*!< Low Power Request Output Override. */ +} spc_lowpower_request_config_t; + +/*! + * @brief Core LDO regulator options in Active mode. + */ +typedef struct _spc_active_mode_core_ldo_option +{ + spc_core_ldo_voltage_level_t CoreLDOVoltage; /*!< Core LDO Regulator Voltage Level selection in Active mode. */ +#if defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS + spc_core_ldo_drive_strength_t CoreLDODriveStrength; /*!< Core LDO Regulator Drive Strength + selection in Active mode */ +#endif /* FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS */ +} spc_active_mode_core_ldo_option_t; + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) +/*! + * @brief System LDO regulator options in Active mode. + */ +typedef struct _spc_active_mode_sys_ldo_option +{ + spc_sys_ldo_voltage_level_t SysLDOVoltage; /*!< System LDO Regulator Voltage Level selection in Active mode. */ + spc_sys_ldo_drive_strength_t SysLDODriveStrength; /*!< System LDO Regulator Drive Strength + selection in Active mode. */ +} spc_active_mode_sys_ldo_option_t; +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) +/*! + * @brief DCDC regulator options in Active mode. + */ +typedef struct _spc_active_mode_dcdc_option +{ + spc_dcdc_voltage_level_t DCDCVoltage; /*!< DCDC Regulator Voltage Level selection in Active mode. */ + spc_dcdc_drive_strength_t DCDCDriveStrength; /*!< DCDC_CORE Regulator Drive Strength selection in Active mode. */ +} spc_active_mode_dcdc_option_t; +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + +/*! + * @brief Core LDO regulator options in Low Power mode. + */ +typedef struct _spc_lowpower_mode_core_ldo_option +{ + spc_core_ldo_voltage_level_t CoreLDOVoltage; /*!< Core LDO Regulator Voltage Level selection in Low Power mode. */ + spc_core_ldo_drive_strength_t CoreLDODriveStrength; /*!< Core LDO Regulator Drive Strength + selection in Low Power mode */ +} spc_lowpower_mode_core_ldo_option_t; + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) +/*! + * @brief System LDO regulator options in Low Power mode. + */ +typedef struct _spc_lowpower_mode_sys_ldo_option +{ + spc_sys_ldo_drive_strength_t SysLDODriveStrength; /*!< System LDO Regulator Drive Strength + selection in Low Power mode. */ +} spc_lowpower_mode_sys_ldo_option_t; +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) +/*! + * @brief DCDC regulator options in Low Power mode. + */ +typedef struct _spc_lowpower_mode_dcdc_option +{ + spc_dcdc_voltage_level_t DCDCVoltage; /*!< DCDC Regulator Voltage Level selection in Low Power mode. */ + spc_dcdc_drive_strength_t DCDCDriveStrength; /*!< DCDC_CORE Regulator Drive Strength selection in Low Power mode. */ +} spc_lowpower_mode_dcdc_option_t; + +/*! + * @brief DCDC Burst configuration. + * @deprecated Do not recommend to use this structure. + */ +typedef struct _spc_dcdc_burst_config +{ + bool sofwareBurstRequest; /*!< Enable/Disable DCDC Software Burst Request. */ + bool externalBurstRequest; /*!< Enable/Disable DCDC External Burst Request. */ + bool stabilizeBurstFreq; /*!< Enable/Disable DCDC frequency stabilization. */ + uint8_t freq; /*!< The frequency of the current burst. */ +} spc_dcdc_burst_config_t; +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + +/*! + * @brief CORE/SYS/IO VDD Voltage Detect options. + */ +typedef struct _spc_voltage_detect_option +{ + bool HVDInterruptEnable; /*!< CORE/SYS/IO VDD High Voltage Detect interrupt enable. */ + bool HVDResetEnable; /*!< CORE/SYS/IO VDD High Voltage Detect reset enable. */ + bool LVDInterruptEnable; /*!< CORE/SYS/IO VDD Low Voltage Detect interrupt enable. */ + bool LVDResetEnable; /*!< CORE/SYS/IO VDD Low Voltage Detect reset enable. */ +} spc_voltage_detect_option_t; + +/*! + * @brief Core Voltage Detect configuration. + */ +typedef struct _spc_core_voltage_detect_config +{ + spc_voltage_detect_option_t option; /*!< Core VDD Voltage Detect option. */ +} spc_core_voltage_detect_config_t; + +/*! + * @brief System Voltage Detect Configuration. + */ +typedef struct _spc_system_voltage_detect_config +{ + spc_voltage_detect_option_t option; /*!< System VDD Voltage Detect option. */ + spc_low_voltage_level_select_t level; /*!< @deprecated, reserved for all devices, will removed in next release. */ +} spc_system_voltage_detect_config_t; + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) && FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) +/*! + * @brief IO Voltage Detect Configuration. + */ +typedef struct _spc_io_voltage_detect_config +{ + spc_voltage_detect_option_t option; /*!< IO VDD Voltage Detect option. */ + spc_low_voltage_level_select_t level; /*!< IO VDD Low-voltage level selection. */ +} spc_io_voltage_detect_config_t; +#endif /* FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD */ + +/*! + * @brief Active mode configuration. + */ +typedef struct _spc_active_mode_regulators_config +{ + spc_bandgap_mode_t bandgapMode; /*!< Specify bandgap mode in active mode. */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) && FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) + bool lpBuff; /*!< Enable/disable CMP bandgap buffer. */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) + spc_active_mode_dcdc_option_t DCDCOption; /*!< Specify DCDC configurations in active mode. */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + spc_active_mode_sys_ldo_option_t SysLDOOption; /*!< Specify System LDO configurations in active mode. */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + + spc_active_mode_core_ldo_option_t CoreLDOOption; /*!< Specify Core LDO configurations in active mode. */ +} spc_active_mode_regulators_config_t; + +/*! + * @brief Low Power Mode configuration. + */ +typedef struct _spc_lowpower_mode_regulators_config +{ + bool lpIREF; /*!< Enable/disable low power IREF in low power modes. */ + spc_bandgap_mode_t bandgapMode; /*!< Specify bandgap mode in low power modes. */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) && FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) + bool lpBuff; /*!< Enable/disable CMP bandgap buffer in low power modes. */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_COREVDD_IVS_EN_BIT) && FSL_FEATURE_MCX_SPC_HAS_COREVDD_IVS_EN_BIT) + bool CoreIVS; /*!< Enable/disable CORE VDD internal voltage scaling. */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_COREVDD_IVS_EN_BIT */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) + spc_lowpower_mode_dcdc_option_t DCDCOption; /*!< Specify DCDC configurations in low power modes. */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) + spc_lowpower_mode_sys_ldo_option_t SysLDOOption; /*!< Specify system LDO configurations in low power modes. */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + + spc_lowpower_mode_core_ldo_option_t CoreLDOOption; /*!< Specify core LDO configurations in low power modes. */ +} spc_lowpower_mode_regulators_config_t; + +/******************************************************************************* + * API + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ + +/*! + * @name SPC Status + * @{ + */ +/*! + * @brief Gets Isolation status for each power domains. + * + * This function gets the status which indicates whether certain + * peripheral and the IO pads are in a latched state as a result + * of having been in POWERDOWN mode. + * + * @param base SPC peripheral base address. + * @return Current isolation status for each power domains. See @ref _spc_power_domains for details. + */ +uint8_t SPC_GetPeriphIOIsolationStatus(SPC_Type *base); + +/*! + * @brief Clears peripherals and I/O pads isolation flags for each power domains. + * + * This function clears peripherals and I/O pads isolation flags for each power domains. + * After recovering from the POWERDOWN mode, user must invoke this function to release the + * I/O pads and certain peripherals to their normal run mode state. Before invoking this + * function, user must restore chip configuration in particular pin configuration for enabled + * WUU wakeup pins. + * + * @param base SPC peripheral base address. + */ +static inline void SPC_ClearPeriphIOIsolationFlag(SPC_Type *base) +{ + base->SC |= SPC_SC_ISO_CLR_MASK; +} + +/*! + * @brief Gets SPC busy status flag. + * + * This function gets SPC busy status flag. When SPC executing any type of power mode + * transition in ACTIVE mode or any of the SOC low power mode, the SPC busy status flag is set + * and this function returns true. When changing CORE LDO voltage level and DCDC voltage level + * in ACTIVE mode, the SPC busy status flag is set and this function return true. + * + * @param base SPC peripheral base address. + * @return Ack busy flag. + * true - SPC is busy. + * false - SPC is not busy. + */ +static inline bool SPC_GetBusyStatusFlag(SPC_Type *base) +{ + return ((base->SC & SPC_SC_BUSY_MASK) != 0UL); +} + +/*! + * @brief Checks system low power request. + * + * @note Only when all power domains request low power mode entry, the result of this function is true. That means when + * all power domains request low power mode entry, the SPC regulators will be controlled by LP_CFG register. + * + * @param base SPC peripheral base address. + * @return The system low power request check result. + * - \b true All power domains have requested low power mode and SPC has entered a low power state and power mode + * configuration are based on the LP_CFG configuration register. + * - \b false SPC in active mode and ACTIVE_CFG register control system power supply. + */ +static inline bool SPC_CheckLowPowerReqest(SPC_Type *base) +{ + return ((base->SC & SPC_SC_SPC_LP_REQ_MASK) == SPC_SC_SPC_LP_REQ_MASK); +} + +/*! + * @brief Clears system low power request, set SPC in active mode. + * + * @param base SPC peripheral base address. + */ +static inline void SPC_ClearLowPowerRequest(SPC_Type *base) +{ + base->SC |= SPC_SC_SPC_LP_REQ_MASK; +} + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SWITCH_STATE_BIT) && FSL_FEATURE_MCX_SPC_HAS_SWITCH_STATE_BIT) +/*! + * @brief Checks whether the power switch is on. + * + * @param base SPC peripheral base address. + * + * @retval true The power switch is on. + * @retval false The power switch is off. + */ +static inline bool SPC_CheckSwitchState(SPC_Type *base) +{ + return ((base->SC & SPC_SC_SWITCH_STATE_MASK) != 0UL); +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_SWITCH_STATE_BIT */ + +/*! + * @brief Gets selected power domain's requested low power mode. + * + * @param base SPC peripheral base address. + * @param powerDomainId Power Domain Id, please refer to @ref spc_power_domain_id_t. + * + * @return The selected power domain's requested low power mode, please refer to @ref spc_power_domain_low_power_mode_t. + */ +spc_power_domain_low_power_mode_t SPC_GetPowerDomainLowPowerMode(SPC_Type *base, spc_power_domain_id_t powerDomainId); + +/*! + * @brief Checks power domain's low power request. + * + * @param base SPC peripheral base address. + * @param powerDomainId Power Domain Id, please refer to @ref spc_power_domain_id_t. + * @return The result of power domain's low power request. + * - \b true The selected power domain requests low power mode entry. + * - \b false The selected power domain does not request low power mode entry. + */ +static inline bool SPC_CheckPowerDomainLowPowerRequest(SPC_Type *base, spc_power_domain_id_t powerDomainId) +{ + assert((uint8_t)powerDomainId < SPC_PD_STATUS_COUNT); + return ((base->PD_STATUS[(uint8_t)powerDomainId] & SPC_PD_STATUS_PWR_REQ_STATUS_MASK) == + SPC_PD_STATUS_PWR_REQ_STATUS_MASK); +} + +/*! + * @brief Clears selected power domain's low power request flag. + * + * @param base SPC peripheral base address. + * @param powerDomainId Power Domain Id, please refer to @ref spc_power_domain_id_t. + */ +static inline void SPC_ClearPowerDomainLowPowerRequestFlag(SPC_Type *base, spc_power_domain_id_t powerDomainId) +{ + assert((uint8_t)powerDomainId < SPC_PD_STATUS_COUNT); + base->PD_STATUS[(uint8_t)powerDomainId] |= SPC_PD_STATUS_PD_LP_REQ_MASK; +} + +/*! @} */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SRAMRETLDO_REG) && FSL_FEATURE_MCX_SPC_HAS_SRAMRETLDO_REG) +/*! + * @name SRAM Retention LDO Control APIs + * @{ + */ + +/*! + * @brief Trims SRAM retention regulator reference voltage, trim step is 12 mV, range is around 0.48V to 0.85V. + * + * @param base SPC peripheral base address. + * @param trimValue Reference voltage trim value. + */ +static inline void SPC_TrimSRAMLdoRefVoltage(SPC_Type *base, uint8_t trimValue) +{ + base->SRAMRETLDO_REFTRIM = + ((base->SRAMRETLDO_REFTRIM & ~SPC_SRAMRETLDO_REFTRIM_REFTRIM_MASK) | SPC_SRAMRETLDO_REFTRIM_REFTRIM(trimValue)); +} + +/*! + * @brief Enables/disables SRAM retention LDO. + * + * @param base SPC peripheral base address. + * @param enable Used to enable/disable SRAM LDO : + * - \b true Enable SRAM LDO; + * - \b false Disable SRAM LDO. + */ +static inline void SPC_EnableSRAMLdo(SPC_Type *base, bool enable) +{ + if (enable) + { + base->SRAMRETLDO_CNTRL |= SPC_SRAMRETLDO_CNTRL_SRAMLDO_ON_MASK; + } + else + { + base->SRAMRETLDO_CNTRL &= ~SPC_SRAMRETLDO_CNTRL_SRAMLDO_ON_MASK; + } +} + +/*! + * @brief + * + * @todo Need to check. + * + * @param base SPC peripheral base address. + * @param mask The OR'ed value of SRAM Array. + */ +static inline void SPC_RetainSRAMArray(SPC_Type *base, uint8_t mask) +{ + base->SRAMRETLDO_CNTRL |= SPC_SRAMRETLDO_CNTRL_SRAM_RET_EN(mask); +} + +/*! @} */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_SRAMRETLDO_REG */ + +/*! + * @name Low Power Request configuration + * @{ + */ +/*! + * @brief Configs Low power request output pin. + * + * This function config the low power request output pin + * + * @param base SPC peripheral base address. + * @param config Pointer the @ref spc_lowpower_request_config_t structure. + */ +void SPC_SetLowPowerRequestConfig(SPC_Type *base, const spc_lowpower_request_config_t *config); + +/*! @} */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_CFG_REG) && FSL_FEATURE_MCX_SPC_HAS_CFG_REG) +/*! + * @name Integrated Power Switch Control APIs + * @{ + */ + +/*! + * @brief Enables/disables the integrated power switch manually. + * + * @param base SPC peripheral base address. + * @param enable Used to enable/disable the integrated power switch: + * - \b true Enable the integrated power switch; + * - \b false Disable the integrated power switch. + */ +static inline void SPC_EnableIntegratedPowerSwitchManually(SPC_Type *base, bool enable) +{ + if (enable) + { + base->CFG |= (SPC_CFG_INTG_PWSWTCH_SLEEP_ACTIVE_EN_MASK | SPC_CFG_INTG_PWSWTCH_WKUP_ACTIVE_EN_MASK); + } + else + { + base->CFG &= ~(SPC_CFG_INTG_PWSWTCH_SLEEP_ACTIVE_EN_MASK | SPC_CFG_INTG_PWSWTCH_WKUP_ACTIVE_EN_MASK); + } +} + +/*! + * @brief Enables/disables the integrated power switch automatically. + * + * To gate the integrated power switch when chip enter low power modes, and ungate the switch after wake-up from low + * power modes: + * @code + * SPC_EnableIntegratedPowerSwitchAutomatically(SPC, true, true); + * @endcode + * + * @param base SPC peripheral base address. + * @param sleepGate Enable the integrated power switch when chip enter low power modes: + * - \b true SPC asserts an output pin at low-power entry to power-gate the switch; + * - \b false SPC does not assert an output pin at low-power entry to power-gate the switch. + * @param wakeupUngate Enables the switch after wake-up from low power modes: + * - \b true SPC asserts an output pin at low-power exit to power-ungate the switch; + * - \b false SPC does not assert an output pin at low-power exit to power-ungate the switch. + */ +static inline void SPC_EnableIntegratedPowerSwitchAutomatically(SPC_Type *base, bool sleepGate, bool wakeupUngate) +{ + uint32_t tmp32 = ((base->CFG) & ~(SPC_CFG_INTG_PWSWTCH_SLEEP_EN_MASK | SPC_CFG_INTG_PWSWTCH_WKUP_EN_MASK)); + + tmp32 |= SPC_CFG_INTG_PWSWTCH_SLEEP_EN(sleepGate) | SPC_CFG_INTG_PWSWTCH_WKUP_EN(wakeupUngate); + + base->CFG = tmp32; +} + +/*! @} */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_CFG_REG */ + +#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) +/*! + * @name VDD Core Glitch Detector Control APIs + * @{ + */ + +/*! + * @brief Configures VDD Core Glitch detector, including ripple counter selection, timeout value and so on. + * + * @param base SPC peripheral base address. + * @param config Pointer to the structure in type of @ref spc_vdd_core_glitch_detector_config_t. + */ +void SPC_ConfigVddCoreGlitchDetector(SPC_Type *base, const spc_vdd_core_glitch_detector_config_t *config); + +/*! + * @brief Checks selected 4-bit glitch ripple counter's output. + * + * @param base SPC peripheral base address. + * @param rippleCounter The ripple counter to check, please refer to @ref spc_vdd_core_glitch_ripple_counter_select_t. + * + * @retval true The selected ripple counter output is 1, will generate interrupt or reset based on settings. + * @retval false The selected ripple counter output is 0. + */ + +static inline bool SPC_CheckGlitchRippleCounterOutput(SPC_Type *base, + spc_vdd_core_glitch_ripple_counter_select_t rippleCounter) +{ + return ((base->VDD_CORE_GLITCH_DETECT_SC & SPC_VDD_CORE_GLITCH_DETECT_SC_GLITCH_DETECT_FLAG_MASK) == + SPC_VDD_CORE_GLITCH_DETECT_SC_GLITCH_DETECT_FLAG(1UL << (uint32_t)(rippleCounter))); +} + +/*! + * @brief Clears output of selected glitch ripple counter. + * + * @param base SPC peripheral base address. + * @param rippleCounter The ripple counter to check, please refer to @ref spc_vdd_core_glitch_ripple_counter_select_t. + */ +static inline void SPC_ClearGlitchRippleCounterOutput(SPC_Type *base, + spc_vdd_core_glitch_ripple_counter_select_t rippleCounter) +{ + base->VDD_CORE_GLITCH_DETECT_SC |= + SPC_VDD_CORE_GLITCH_DETECT_SC_GLITCH_DETECT_FLAG(1UL << (uint32_t)(rippleCounter)); +} + +/*! + * @brief After invoking this function, writes to SPC_VDD_CORE_GLITCH_DETECT_SC[RE] register are ignored. + * + * @param base SPC peripheral base address. + */ +static inline void SPC_LockVddCoreVoltageGlitchDetectResetControl(SPC_Type *base) +{ + base->VDD_CORE_GLITCH_DETECT_SC |= SPC_VDD_CORE_GLITCH_DETECT_SC_LOCK_MASK; +} + +/*! + * @brief After invoking this function, writes to SPC_VDD_CORE_GLITCH_DETECT_SC[RE] register are allowed. + * + * @param base SPC peripheral base address. + */ +static inline void SPC_UnlockVddCoreVoltageGlitchDetectResetControl(SPC_Type *base) +{ + base->VDD_CORE_GLITCH_DETECT_SC &= ~SPC_VDD_CORE_GLITCH_DETECT_SC_LOCK_MASK; +} + +/*! + * @brief Checks if SPC_VDD_CORE_GLITCH_DETECT_SC[RE] register is writable. + * + * @param base SPC peripheral base address. + * + * @retval true SPC_VDD_CORE_GLITCH_DETECT_SC[RE] register is writable. + * @retval false SPC_VDD_CORE_GLITCH_DETECT_SC[RE] register is not writable. + */ +static inline bool SPC_CheckVddCoreVoltageGlitchResetControlState(SPC_Type *base) +{ + return ((base->VDD_CORE_GLITCH_DETECT_SC & SPC_VDD_CORE_GLITCH_DETECT_SC_LOCK_MASK) != 0UL); +} + +/*! @} */ +#endif + +/*! + * @name SRAM Control APIs + * @{ + */ + +/*! + * @brief Set SRAM operate voltage. + * + * @param base SPC peripheral base address. + * @param config The pointer to @ref spc_sram_voltage_config_t, specifies the configuration of sram voltage. + */ +void SPC_SetSRAMOperateVoltage(SPC_Type *base, const spc_sram_voltage_config_t *config); + +/*! @} */ + +/*! + * @name Active Mode configuration + * @{ + */ + +/*! + * @brief Gets the Bandgap mode in Active mode. + * + * @param base SPC peripheral base address. + * @return Bandgap mode in the type of @ref spc_bandgap_mode_t enumeration. + */ +static inline spc_bandgap_mode_t SPC_GetActiveModeBandgapMode(SPC_Type *base) +{ + return (spc_bandgap_mode_t)(uint32_t)((base->ACTIVE_CFG & SPC_ACTIVE_CFG_BGMODE_MASK) >> + SPC_ACTIVE_CFG_BGMODE_SHIFT); +} + +/*! + * @brief Gets all voltage detectors status in Active mode. + * + * @param base SPC peripheral base address. + * @return All voltage detectors status in Active mode. + */ +static inline uint32_t SPC_GetActiveModeVoltageDetectStatus(SPC_Type *base) +{ + uint32_t state; + state = base->ACTIVE_CFG & + ( +#if (defined(FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) && FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) + SPC_ACTIVE_CFG_IO_HVDE_MASK | SPC_ACTIVE_CFG_IO_LVDE_MASK | + +#endif /* FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD */ + SPC_ACTIVE_CFG_SYS_HVDE_MASK | SPC_ACTIVE_CFG_SYS_LVDE_MASK | SPC_ACTIVE_CFG_CORE_LVDE_MASK + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) && FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) + | SPC_ACTIVE_CFG_CORE_HVDE_MASK + +#endif /* FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD */ + ); + return state; +} + +/*! + * @brief Configs Bandgap mode in Active mode. + * + * @note To disable bandgap in Active mode: + * 1. Disable all LVD's and HVD's in active mode; + * 2. Disable Glitch detect; + * 3. Configrue LDO's and DCDC to low drive strength in active mode; + * 4. Invoke this function to disable bandgap in active mode; + * otherwise the error status will be reported. + * + * @note Some other system resources(such as PLL, CMP) require bandgap to be enabled, to disable bandgap please + * take care of other system resources. + * + * @param base SPC peripheral base address. + * @param mode The Bandgap mode be selected. + * + * @retval #kStatus_SPC_BandgapModeWrong The Bandgap can not be disabled in active mode. + * @retval #kStatus_Success Config Bandgap mode in Active power mode successful. + */ +status_t SPC_SetActiveModeBandgapModeConfig(SPC_Type *base, spc_bandgap_mode_t mode); + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) && FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) +/*! + * @brief Enables/Disable the CMP Bandgap Buffer in Active mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable CMP Bandgap buffer. + * true - Enable Buffer Stored Reference voltage to CMP. + * false - Disable Buffer Stored Reference voltage to CMP. + */ +static inline void SPC_EnableActiveModeCMPBandgapBuffer(SPC_Type *base, bool enable) +{ + if (enable) + { + base->ACTIVE_CFG |= SPC_ACTIVE_CFG_LPBUFF_EN_MASK; + } + else + { + base->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_LPBUFF_EN_MASK; + } +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT */ + +/*! + * @brief Sets the delay when the regulators change voltage level in Active mode. + * + * @param base SPC peripheral base address. + * @param delay The number of SPC timer clock cycles. + */ +static inline void SPC_SetActiveModeVoltageTrimDelay(SPC_Type *base, uint16_t delay) +{ + base->ACTIVE_VDELAY = SPC_ACTIVE_VDELAY_ACTIVE_VDELAY(delay); +} + +/*! + * @brief Configs all settings of regulators in Active mode at a time. + * + * @note This function is used to overwrite all settings of regulators(including bandgap mode, regulators' + * drive strength and voltage level) in active mode at a time. + * + * @note Enable/disable LVDs/HVDs before invoking this function. + * + * @note This function will check input parameters based on hardware restrictions before setting registers, if input + * parameters do not satisfy hardware restrictions the specific error will be reported. + * + * + * @note Some hardware restrictions not covered, application should be aware of this and follow this hardware + * restrictions otherwise some unkown issue may occur: + * 1. If Core LDO's drive strength are set to same value in both Active mode and low power mode, + * the voltage level should also set to same value. + * 2. When switching Core LDO's drive strength from low to normal, ensure the LDO_CORE high voltage level is set + * to same level that was set prior to switching to the LDO_CORE drive strength. Otherwise, if the LVDs are + * enabled, an unexpected LVD can occur. + * + * @note If this function can not satisfy some tricky settings, please invoke other APIs in low-level function group. + * + * @param base SPC peripheral base address. + * @param config Pointer to spc_active_mode_regulators_config_t structure. + * + * @retval #kStatus_Success Config regulators in Active power mode successful. + * @retval #kStatus_SPC_BandgapModeWrong Based on input setting, bandgap can not be disabled. + * @retval #kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * @retval #kStatus_SPC_CORELDOLowDriveStrengthIgnore Any of LVDs/HVDs kept enabled before invoking this function. + * @retval #kStatus_SPC_SYSLDOOverDriveVoltageFail Fail to regulator to Over Drive Voltage due to + * System VDD HVD is not disabled. + * @retval #kStatus_SPC_SYSLDOLowDriveStrengthIgnore Any of LVDs/HVDs kept enabled before invoking this function. + * @retval #kStatus_SPC_CORELDOVoltageWrong Core LDO and System LDO do not have same voltage level. + */ +status_t SPC_SetActiveModeRegulatorsConfig(SPC_Type *base, const spc_active_mode_regulators_config_t *config); + +#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) +/*! + * @brief Disables/Enables VDD Core Glitch Detect in Active mode. + * + * @note State of glitch detect disable feature will be ignored if bandgap is disabled and + * glitch detect hardware will be forced to OFF state. + * + * @param base SPC peripheral base address. + * @param disable Used to disable/enable VDD Core Glitch detect feature. + * - \b true Disable VDD Core Low Voltage detect; + * - \b false Enable VDD Core Low Voltage detect. + */ +static inline void SPC_DisableActiveModeVddCoreGlitchDetect(SPC_Type *base, bool disable) +{ + if (disable) + { + base->ACTIVE_CFG |= SPC_ACTIVE_CFG_GLITCH_DETECT_DISABLE_MASK; + } + else + { + base->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_GLITCH_DETECT_DISABLE_MASK; + } +} + +/*! + * @brief Check if Glitch detect hardware is enabled in active mode. + * + * @param base SPC peripheral base address. + * @return Indicate if Glitch detector is enabled. + */ +static inline bool SPC_CheckActiveModeVddCoreGlitchDetectEnabled(SPC_Type *base) +{ + if ((base->ACTIVE_CFG & SPC_ACTIVE_CFG_GLITCH_DETECT_DISABLE_MASK) == 0UL) + { + return true; + } + else + { + return false; + } +} + +#endif /* FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT */ + +/*! + * @brief Enables analog modules in active mode. + * + * @param base SPC peripheral base address. + * @param maskValue The mask of analog modules to enable in active mode, should be the OR'ed value + * of @ref spc_analog_module_control. + */ +static inline void SPC_EnableActiveModeAnalogModules(SPC_Type *base, uint32_t maskValue) +{ + base->ACTIVE_CFG1 |= SPC_ACTIVE_CFG1_SOC_CNTRL(maskValue); +} + +/*! + * @brief Disables analog modules in active mode. + * + * @param base SPC peripheral base address. + * @param maskValue The mask of analog modules to disable in active mode, should be the OR'ed value + * of @ref spc_analog_module_control. + */ +static inline void SPC_DisableActiveModeAnalogModules(SPC_Type *base, uint32_t maskValue) +{ + base->ACTIVE_CFG1 &= ~SPC_ACTIVE_CFG1_SOC_CNTRL(maskValue); +} + +/*! + * @brief Gets enabled analog modules that enabled in active mode. + * + * @param base SPC peripheral base address. + * + * @return The mask of enabled analog modules that enabled in active mode. + */ +static inline uint32_t SPC_GetActiveModeEnabledAnalogModules(SPC_Type *base) +{ + return base->ACTIVE_CFG1; +} + +/*! @} */ + +/*! + * @name Low Power mode configuration + * @{ + */ + +/*! + * @brief Gets the Bandgap mode in Low Power mode. + * + * @param base SPC peripheral base address. + * @return Bandgap mode in the type of @ref spc_bandgap_mode_t enumeration. + */ +static inline spc_bandgap_mode_t SPC_GetLowPowerModeBandgapMode(SPC_Type *base) +{ + return (spc_bandgap_mode_t)(uint32_t)((base->LP_CFG & SPC_LP_CFG_BGMODE_MASK) >> SPC_LP_CFG_BGMODE_SHIFT); +} + +/*! + * @brief Gets the status of all voltage detectors in Low Power mode. + * + * @param base SPC peripheral base address. + * @return The status of all voltage detectors in low power mode. + */ +static inline uint32_t SPC_GetLowPowerModeVoltageDetectStatus(SPC_Type *base) +{ + uint32_t state; + state = base->LP_CFG & ( +#if (defined(FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) && FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) + SPC_LP_CFG_IO_HVDE_MASK | SPC_LP_CFG_IO_LVDE_MASK | + +#endif /* FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD */ + SPC_LP_CFG_SYS_HVDE_MASK | SPC_LP_CFG_SYS_LVDE_MASK | SPC_LP_CFG_CORE_LVDE_MASK + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) && FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) + | SPC_LP_CFG_CORE_HVDE_MASK + +#endif /* FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD */ + ); + return state; +} + +/*! + * @brief Enables/Disables Low Power IREF in low power modes. + * + * This function enables/disables Low Power IREF. Low Power IREF can only get + * disabled in Deep power down mode. In other low power modes, the Low Power IREF + * is always enabled. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable Low Power IREF. + * true - Enable Low Power IREF for Low Power modes. + * false - Disable Low Power IREF for Deep Power Down mode. + */ +static inline void SPC_EnableLowPowerModeLowPowerIREF(SPC_Type *base, bool enable) +{ + if (enable) + { + base->LP_CFG |= SPC_LP_CFG_LP_IREFEN_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_LP_IREFEN_MASK; + } +} + +/*! + * @brief Configs Bandgap mode in Low Power mode. + * + * @note To disable Bandgap in Low-power mode: + * 1. Disable all LVD's ad HVD's in low power mode; + * 2. Disable Glitch detect in low power mode; + * 3. Configure LDO's and DCDC to low drive strength in low power mode; + * 4. Disable bandgap in low power mode; + * Otherwise, the error status will be reported. + * + * @note Some other system resources(such as PLL, CMP) require bandgap to be enabled, to disable bandgap please + * take care of other system resources. + * + * @param base SPC peripheral base address. + * @param mode The Bandgap mode be selected. + * + * @retval #kStatus_SPC_BandgapModeWrong The bandgap mode setting in Low Power mode is wrong. + * @retval #kStatus_Success Config Bandgap mode in Low Power power mode successful. + */ +status_t SPC_SetLowPowerModeBandgapmodeConfig(SPC_Type *base, spc_bandgap_mode_t mode); + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SRAMLDO_DPD_ON_BIT) && FSL_FEATURE_MCX_SPC_HAS_SRAMLDO_DPD_ON_BIT) +/*! + * @brief Enables/disables SRAM_LDO deep power low power IREF. + * + * @param base SPC peripheral base address. + * @param enable Used to enable/disable low power IREF : + * - \b true: Low Power IREF is enabled ; + * - \b false: Low Power IREF is disabled for power saving. + */ +static inline void SPC_EnableSRAMLdOLowPowerModeIREF(SPC_Type *base, bool enable) +{ + if (enable) + { + base->LP_CFG |= SPC_LP_CFG_SRAMLDO_DPD_ON_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_SRAMLDO_DPD_ON_MASK; + } +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_SRAMLDO_DPD_ON_BIT */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) && FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT) +/*! + * @brief Enables/Disables CMP Bandgap Buffer. + * + * This function gates CMP bandgap buffer. CMP bandgap buffer is automatically disabled and turned off + * in Deep Power Down mode. + * + * @deprecated No longer used, please use SPC_EnableLowPowerModeCMPBandgapBuffer as instead. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable CMP Bandgap buffer. + * true - Enable Buffer Stored Reference Voltage to CMP. + * false - Disable Buffer Stored Reference Voltage to CMP. + */ +static inline void SPC_EnableLowPowerModeCMPBandgapBufferMode(SPC_Type *base, bool enable) +{ + if (enable) + { + base->LP_CFG |= SPC_LP_CFG_LPBUFF_EN_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_LPBUFF_EN_MASK; + } +} + +/*! + * @brief Enables/Disables CMP Bandgap Buffer. + * + * This function gates CMP bandgap buffer. CMP bandgap buffer is automatically disabled and turned off + * in Deep Power Down mode. + * + * @deprecated No longer used. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable CMP Bandgap buffer. + * true - Enable Buffer Stored Reference Voltage to CMP. + * false - Disable Buffer Stored Reference Voltage to CMP. + */ +static inline void SPC_EnableLowPowerModeCMPBandgapBuffer(SPC_Type *base, bool enable) +{ + if (enable) + { + base->LP_CFG |= SPC_LP_CFG_LPBUFF_EN_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_LPBUFF_EN_MASK; + } +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_LPBUFF_EN_BIT */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_COREVDD_IVS_EN_BIT) && FSL_FEATURE_MCX_SPC_HAS_COREVDD_IVS_EN_BIT) +/*! + * @brief Enables/Disables CORE VDD IVS(Internal Voltage Scaling) in power down modes. + * + * This function gates CORE VDD IVS. When enabled, the IVS regulator will scale the + * external input CORE VDD to a lower voltage level to reduce internal leakage. + * IVS is invalid in Sleep or Deep power down mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable IVS. + * true - enable CORE VDD IVS in Power Down mode. + * false - disable CORE VDD IVS in Power Down mode. + */ +static inline void SPC_EnableLowPowerModeCoreVDDInternalVoltageScaling(SPC_Type *base, bool enable) +{ + if (enable) + { + base->LP_CFG |= SPC_LP_CFG_COREVDD_IVS_EN_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_COREVDD_IVS_EN_MASK; + } +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_COREVDD_IVS_EN_BIT */ + +/*! + * @brief Sets the delay when exit the low power modes. + * + * @param base SPC peripheral base address. + * @param delay The number of SPC timer clock cycles that the SPC waits on exit from low power modes. + */ +static inline void SPC_SetLowPowerWakeUpDelay(SPC_Type *base, uint16_t delay) +{ + base->LPWKUP_DELAY = SPC_LPWKUP_DELAY_LPWKUP_DELAY(delay); +} + +/*! + * @brief Configs all settings of regulators in Low power mode at a time. + * + * @note This function is used to overwrite all settings of regulators(including bandgap mode, regulators' + * drive strength and voltage level) in low power mode at a time. + * + * @note Enable/disable LVDs/HVDs before invoking this function. + * + * @note This function will check input parameters based on hardware restrictions before setting registers, if input + * parameters do not satisfy hardware restrictions the specific error will be reported. + * + * @note Some hardware restrictions not covered, application should be aware of this and follow this hardware + * restrictions otherwise some unkown issue may occur: + * 1. If Core LDO's drive strength are set to same value in both Active mode and low power mode, + * the voltage level should also set to same value. + * 2. When switching Core LDO's drive strength from low to normal, ensure the LDO_CORE high voltage level is set + * to same level that was set prior to switching to the LDO_CORE drive strength. Otherwise, if the LVDs are + * enabled, an unexpected LVD can occur. + * + * @note If this function can not satisfy some tricky settings, please invoke other APIs in low-level function group. + * + * @param base SPC peripheral base address. + * @param config Pointer to spc_lowpower_mode_regulators_config_t structure. + * @retval #kStatus_Success Config regulators in Low power mode successful. + * @retval #kStatus_SPC_BandgapModeWrong The bandgap should not be disabled based on input settings. + * @retval #kStatus_SPC_CORELDOLowDriveStrengthIgnore Set driver strength to low will be ignored. + * @retval #kStatus_SPC_SYSLDOLowDriveStrengthIgnore Set driver strength to low will be ignored. + * @retval #kStatus_SPC_CORELDOVoltageWrong Core LDO and System LDO do not have same voltage level. + */ +status_t SPC_SetLowPowerModeRegulatorsConfig(SPC_Type *base, const spc_lowpower_mode_regulators_config_t *config); + +#if !(defined(FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) && FSL_FEATURE_MCX_SPC_HAS_NO_GLITCH_DETECT) +/*! + * @brief Disable/Enable VDD Core Glitch Detect in low power mode. + * + * @note State of glitch detect disable feature will be ignored if bandgap is disabled and + * glitch detect hardware will be forced to OFF state. + * + * @param base SPC peripheral base address. + * @param disable Used to disable/enable VDD Core Glitch detect feature. + * - \b true Disable VDD Core Low Voltage detect; + * - \b false Enable VDD Core Low Voltage detect. + */ +static inline void SPC_DisableLowPowerModeVddCoreGlitchDetect(SPC_Type *base, bool disable) +{ + if (disable) + { + base->LP_CFG |= SPC_LP_CFG_GLITCH_DETECT_DISABLE_MASK; + } + else + { + base->LP_CFG &= ~SPC_LP_CFG_GLITCH_DETECT_DISABLE_MASK; + } +} + +/*! + * @brief Check if Glitch detect hardware is enabled in low power mode. + * + * @param base SPC peripheral base address. + * @return Indicate if Glitch detector is enabled. + */ +static inline bool SPC_CheckLowPowerModeVddCoreGlitchDetectEnabled(SPC_Type *base) +{ + if ((base->LP_CFG & SPC_LP_CFG_GLITCH_DETECT_DISABLE_MASK) == 0UL) + { + return true; + } + else + { + return false; + } +} +#endif + +/*! + * @brief Enables analog modules in low power modes. + * + * @param base SPC peripheral base address. + * @param maskValue The mask of analog modules to enable in low power modes, should be OR'ed value + of @ref spc_analog_module_control. + */ +static inline void SPC_EnableLowPowerModeAnalogModules(SPC_Type *base, uint32_t maskValue) +{ + base->LP_CFG1 |= SPC_LP_CFG1_SOC_CNTRL(maskValue); +} + +/*! + * @brief Disables analog modules in low power modes. + * + * @param base SPC peripheral base address. + * @param maskValue The mask of analog modules to disable in low power modes, should be OR'ed value + of @ref spc_analog_module_control. + */ +static inline void SPC_DisableLowPowerModeAnalogModules(SPC_Type *base, uint32_t maskValue) +{ + base->LP_CFG1 &= ~SPC_LP_CFG1_SOC_CNTRL(maskValue); +} + +/*! + * @brief Gets enabled analog modules that enabled in low power modes. + * + * @param base SPC peripheral base address. + * + * @return The mask of enabled analog modules that enabled in low power modes. + */ +static inline uint32_t SPC_GetLowPowerModeEnabledAnalogModules(SPC_Type *base) +{ + return base->LP_CFG1; +} + +/*! @} */ + +/*! + * @name Voltage Detect Status + * @{ + */ +/*! + * @brief Get Voltage Detect Status Flags. + * + * @param base SPC peripheral base address. + * @return Voltage Detect Status Flags. See @ref _spc_voltage_detect_flags for details. + */ +static inline uint8_t SPC_GetVoltageDetectStatusFlag(SPC_Type *base) +{ + return (uint8_t)(base->VD_STAT); +} + +/*! + * @brief Clear Voltage Detect Status Flags. + * + * @param base SPC peripheral base address. + * @param mask The mask of the voltage detect status flags. See @ref _spc_voltage_detect_flags for details. + */ +static inline void SPC_ClearVoltageDetectStatusFlag(SPC_Type *base, uint8_t mask) +{ + base->VD_STAT |= mask; +} + +/*! @} */ + +/*! + * @name Voltage Detect configuration for Core voltage domain. + * @{ + */ + +/*! + * @brief Configs CORE voltage detect options. + * + * @note: Setting both the voltage detect interrupt and reset + * enable will cause interrupt to be generated on exit from reset. + * If those conditioned is not desired, interrupt/reset so only one is enabled. + * + * @param base SPC peripheral base address. + * @param config Pointer to spc_core_voltage_detect_config_t structure. + */ +void SPC_SetCoreVoltageDetectConfig(SPC_Type *base, const spc_core_voltage_detect_config_t *config); + +/*! + * @brief Locks Core voltage detect reset setting. + * + * This function locks core voltage detect reset setting. After invoking this function + * any configuration of Core voltage detect reset will be ignored. + * + * @param base SPC peripheral base address. + */ +static inline void SPC_LockCoreVoltageDetectResetSetting(SPC_Type *base) +{ + base->VD_CORE_CFG |= SPC_VD_CORE_CFG_LOCK_MASK; +} + +/*! + * @brief Unlocks Core voltage detect reset setting. + * + * This function unlocks core voltage detect reset setting. If locks the Core + * voltage detect reset setting, invoking this function to unlock. + * + * @param base SPC peripheral base address. + */ +static inline void SPC_UnlockCoreVoltageDetectResetSetting(SPC_Type *base) +{ + base->VD_CORE_CFG &= ~SPC_VD_CORE_CFG_LOCK_MASK; +} + +/*! + * @brief Enables/Disables the Core Low Voltage Detector in Active mode. + * + * @note If the CORE_LDO low voltage detect is enabled in Active mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable Core LVD. + * true - Enable Core Low voltage detector in active mode. + * false - Disable Core Low voltage detector in active mode. + * + * @retval #kStatus_Success Enable/Disable Core Low Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeCoreLowVoltageDetect(SPC_Type *base, bool enable); + +/*! + * @brief Enables/Disables the Core Low Voltage Detector in Low Power mode. + * + * This function enables/disables the Core Low Voltage Detector. + * If enabled the Core Low Voltage detector. The Bandgap mode in + * low power mode must be programmed so that Bandgap is enabled. + * + * @note If the CORE_LDO low voltage detect is enabled in Low Power mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low in Low Power mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable Core HVD. + * true - Enable Core Low voltage detector in low power mode. + * false - Disable Core Low voltage detector in low power mode. + * + * @retval #kStatus_Success Enable/Disable Core Low Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeCoreLowVoltageDetect(SPC_Type *base, bool enable); + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) && FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD) +/*! + * @brief Enables/Disables the Core High Voltage Detector in Active mode. + * + * @note If the CORE_LDO high voltage detect is enabled in Active mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable Core HVD. + * true - Enable Core High voltage detector in active mode. + * false - Disable Core High voltage detector in active mode. + * + * @retval #kStatus_Success Enable/Disable Core High Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeCoreHighVoltageDetect(SPC_Type *base, bool enable); + +/*! + * @brief Enables/Disables the Core High Voltage Detector in Low Power mode. + * + * This function enables/disables the Core High Voltage Detector. + * If enabled the Core High Voltage detector. The Bandgap mode in + * low power mode must be programmed so that Bandgap is enabled. + * + * @note If the CORE_LDO high voltage detect is enabled in Low Power mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low in low power mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable Core HVD. + * true - Enable Core High voltage detector in low power mode. + * false - Disable Core High voltage detector in low power mode. + * + * @retval #kStatus_Success Enable/Disable Core High Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeCoreHighVoltageDetect(SPC_Type *base, bool enable); +#endif /* FSL_FEATURE_MCX_SPC_HAS_COREVDD_HVD */ + +/*! @} */ + +/*! + * @name Voltage detect configuration for System Voltage domain + * @{ + */ +/*! + * @brief Set system VDD Low-voltage level selection. + * + * This function selects the system VDD low-voltage level. Changing system VDD low-voltage level + * must be done after disabling the System VDD low voltage reset and interrupt. + * + * @deprecated In latest RM, reserved for all devices, will removed in next release. + * + * @param base SPC peripheral base address. + * @param level System VDD Low-Voltage level selection. + */ +void SPC_SetSystemVDDLowVoltageLevel(SPC_Type *base, spc_low_voltage_level_select_t level); + +/*! + * @brief Configs SYS voltage detect options. + * + * This function config SYS voltage detect options. + * @note: Setting both the voltage detect interrupt and reset + * enable will cause interrupt to be generated on exit from reset. + * If those conditioned is not desired, interrupt/reset so only one is enabled. + * + * @param base SPC peripheral base address. + * @param config Pointer to spc_system_voltage_detect_config_t structure. + */ +void SPC_SetSystemVoltageDetectConfig(SPC_Type *base, const spc_system_voltage_detect_config_t *config); + +/*! + * @brief Lock System voltage detect reset setting. + * + * This function locks system voltage detect reset setting. After invoking this function + * any configuration of System Voltage detect reset will be ignored. + * + * @param base SPC peripheral base address. + */ +static inline void SPC_LockSystemVoltageDetectResetSetting(SPC_Type *base) +{ + base->VD_SYS_CFG |= SPC_VD_SYS_CFG_LOCK_MASK; +} + +/*! + * @brief Unlock System voltage detect reset setting. + * + * This function unlocks system voltage detect reset setting. If locks the System + * voltage detect reset setting, invoking this function to unlock. + * + * @param base SPC peripheral base address. + */ +static inline void SPC_UnlockSystemVoltageDetectResetSetting(SPC_Type *base) +{ + base->VD_SYS_CFG &= ~SPC_VD_SYS_CFG_LOCK_MASK; +} + +/*! + * @brief Enables/Disables the System High Voltage Detector in Active mode. + * + * @note If the System_LDO high voltage detect is enabled in Active mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low in Active mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable System HVD. + * true - Enable System High voltage detector in active mode. + * false - Disable System High voltage detector in active mode. + * + * @retval #kStatus_Success Enable/Disable System High Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeSystemHighVoltageDetect(SPC_Type *base, bool enable); + +/*! + * @brief Enables/Disable the System Low Voltage Detector in Active mode. + * + * @note If the System_LDO low voltage detect is enabled in Active mode, + * please note that the bandgap must be enabled and the drive strength of each + * regulator must not set to low in Active mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable System LVD. + * true - Enable System Low voltage detector in active mode. + * false - Disable System Low voltage detector in active mode. + * + * @retval #kStatus_Success Enable/Disable the System Low Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeSystemLowVoltageDetect(SPC_Type *base, bool enable); + +/*! + * @brief Enables/Disables the System High Voltage Detector in Low Power mode. + * + * @note If the System_LDO high voltage detect is enabled in Low Power mode, please note + * that the bandgap must be enabled and the drive strength of each regulator must + * not set to low in Low Power mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable System HVD. + * true - Enable System High voltage detector in low power mode. + * false - Disable System High voltage detector in low power mode. + * + * @retval #kStatus_Success Enable/Disable System High Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeSystemHighVoltageDetect(SPC_Type *base, bool enable); + +/*! + * @brief Enables/Disables the System Low Voltage Detector in Low Power mode. + * + * @note If the System_LDO low voltage detect is enabled in Low Power mode, + * please note that the bandgap must be enabled and the drive strength of each + * regulator must not set to low in Low Power mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable System HVD. + * true - Enable System Low voltage detector in low power mode. + * false - Disable System Low voltage detector in low power mode. + * + * @retval #kStatus_Success Enables System Low Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeSystemLowVoltageDetect(SPC_Type *base, bool enable); + +/*! @} */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) && FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD) +/*! + * @name Voltage detect configuration for IO voltage domain + * @{ + */ +/*! + * @brief Set IO VDD Low-Voltage level selection. + * + * This function selects the IO VDD Low-voltage level. Changing IO VDD low-voltage level + * must be done after disabling the IO VDD low voltage reset and interrupt. + * + * @param base SPC peripheral base address. + * @param level IO VDD Low-voltage level selection. + */ +void SPC_SetIOVDDLowVoltageLevel(SPC_Type *base, spc_low_voltage_level_select_t level); + +/*! + * @brief Configs IO voltage detect options. + * + * This function config IO voltage detect options. + * @note: Setting both the voltage detect interrupt and reset + * enable will cause interrupt to be generated on exit from reset. + * If those conditioned is not desired, interrupt/reset so only one is enabled. + * + * @param base SPC peripheral base address. + * @param config Pointer to spc_voltage_detect_config_t structure. + */ +void SPC_SetIOVoltageDetectConfig(SPC_Type *base, const spc_io_voltage_detect_config_t *config); + +/*! + * @brief Lock IO Voltage detect reset setting. + * + * This function locks IO voltage detect reset setting. After invoking this function + * any configuration of system voltage detect reset will be ignored. + * + * @param base SPC peripheral base address. + */ +static inline void SPC_LockIOVoltageDetectResetSetting(SPC_Type *base) +{ + base->VD_IO_CFG |= SPC_VD_IO_CFG_LOCK_MASK; +} + +/*! + * @brief Unlock IO voltage detect reset setting. + * + * This function unlocks IO voltage detect reset setting. If locks the IO + * voltage detect reset setting, invoking this function to unlock. + * + * @param base SPC peripheral base address. + */ +static inline void SPC_UnlockIOVoltageDetectResetSetting(SPC_Type *base) +{ + base->VD_IO_CFG &= ~SPC_VD_IO_CFG_LOCK_MASK; +} + +/*! + * @brief Enables/Disables the IO High Voltage Detector in Active mode. + * + * @note If the IO high voltage detect is enabled in Active mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low in Active mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable IO HVD. + * true - Enable IO High voltage detector in active mode. + * false - Disable IO High voltage detector in active mode. + * + * @retval #kStatus_Success Enable/Disable IO High Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeIOHighVoltageDetect(SPC_Type *base, bool enable); + +/*! + * @brief Enables/Disables the IO Low Voltage Detector in Active mode. + * + * @note If the IO low voltage detect is enabled in Active mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low in Active mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable IO LVD. + * true - Enable IO Low voltage detector in active mode. + * false - Disable IO Low voltage detector in active mode. + * + * @retval #kStatus_Success Enable IO Low Voltage Detect successfully. + */ +status_t SPC_EnableActiveModeIOLowVoltageDetect(SPC_Type *base, bool enable); + +/*! + * @brief Enables/Disables the IO High Voltage Detector in Low Power mode. + * + * @note If the IO high voltage detect is enabled in Low Power mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low in Low Power mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable IO HVD. + * true - Enable IO High voltage detector in low power mode. + * false - Disable IO High voltage detector in low power mode. + * + * @retval #kStatus_Success Enable IO High Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeIOHighVoltageDetect(SPC_Type *base, bool enable); + +/*! + * @brief Enables/Disables the IO Low Voltage Detector in Low Power mode. + * + * @note If the IO low voltage detect is enabled in Low Power mode, please note that the bandgap must be enabled + * and the drive strength of each regulator must not set to low in Low Power mode. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable IO LVD. + * true - Enable IO Low voltage detector in low power mode. + * false - Disable IO Low voltage detector in low power mode. + * + * @retval #kStatus_Success Enable/Disable IO Low Voltage Detect in low power mode successfully. + */ +status_t SPC_EnableLowPowerModeIOLowVoltageDetect(SPC_Type *base, bool enable); + +/*! @} */ + +#endif /* FSL_FEATURE_MCX_SPC_HAS_IOVDD_VD */ + +/*! + * @name External Voltage domains configuration + * @{ + */ +/*! + * @brief Configs external voltage domains + * + * This function configs external voltage domains isolation. + * + * @param base SPC peripheral base address. + * @param lowPowerIsoMask The mask of external domains isolate enable during low power mode. Please read the Reference + * Manual for the Bitmap. + * @param IsoMask The mask of external domains isolate. Please read the Reference Manual for the Bitmap. + */ +void SPC_SetExternalVoltageDomainsConfig(SPC_Type *base, uint8_t lowPowerIsoMask, uint8_t IsoMask); + +/*! + * @brief Gets External Domains status. + * + * @param base SPC peripheral base address. + * @return The status of each external domain. + */ +static inline uint8_t SPC_GetExternalDomainsStatus(SPC_Type *base) +{ + return (uint8_t)(base->EVD_CFG >> SPC_EVD_CFG_REG_EVDSTAT_SHIFT); +} + +/*! @} */ + +/*! + * @name Low Level APIs To Set CORE LDO Regulator + * @{ + */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_CNTRL_REG) && FSL_FEATURE_MCX_SPC_HAS_CNTRL_REG) +/*! + * @brief Enable/Disable Core LDO regulator. + * + * @note The CORE LDO enable bit is write-once. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable CORE LDO Regulator. + * true - Enable CORE LDO Regulator. + * false - Disable CORE LDO Regulator. + */ +static inline void SPC_EnableCoreLDORegulator(SPC_Type *base, bool enable) +{ + if (enable) + { + base->CNTRL |= SPC_CNTRL_CORELDO_EN_MASK; + } + else + { + /* + * $Branch Coverage Justification$ + * If CORE_LDO is disabled, all RAMs data will powered off. + */ + base->CNTRL &= ~SPC_CNTRL_CORELDO_EN_MASK; + } +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_CNTRL_REG */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DPDOWN_PULLDOWN_DISABLE_BIT) && \ + FSL_FEATURE_MCX_SPC_HAS_DPDOWN_PULLDOWN_DISABLE_BIT) +/*! + * @brief Enable/Disable the CORE LDO Regulator pull down in Deep Power Down. + * + * @note This function only useful when enabled the CORE LDO Regulator. + * + * @param base SPC peripheral base address. + * @param pulldown Enable/Disable CORE LDO pulldown in Deep Power Down mode. + * true - CORE LDO Regulator will discharge in Deep Power Down mode. + * false - CORE LDO Regulator will not discharge in Deep Power Down mode. + */ +static inline void SPC_PullDownCoreLDORegulator(SPC_Type *base, bool pulldown) +{ + if (pulldown) + { + base->CORELDO_CFG &= ~SPC_CORELDO_CFG_DPDOWN_PULLDOWN_DISABLE_MASK; + } + else + { + base->CORELDO_CFG |= SPC_CORELDO_CFG_DPDOWN_PULLDOWN_DISABLE_MASK; + } +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_DPDOWN_PULLDOWN_DISABLE_BIT */ + +/*! + * @brief Configs Core LDO Regulator in Active mode. + * + * @note The bandgap must be enabled before invoking this function. + * @note To set Core LDO as low drive strength, all HVDs/LVDs must be disabled previously. + * + * @param base SPC peripheral base address. + * @param option Pointer to the spc_active_mode_core_ldo_option_t structure. + * + * @retval kStatus_Success Config Core LDO regulator in Active power mode successful. + * @retval kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * @retval kStatus_SPC_BandgapModeWrong Bandgap should be enabled before invoking this function. + * @retval kStatus_SPC_CORELDOLowDriveStrengthIgnore To set Core LDO as low drive strength, + * all LVDs/HVDs must be disabled before invoking this function. + */ +status_t SPC_SetActiveModeCoreLDORegulatorConfig(SPC_Type *base, const spc_active_mode_core_ldo_option_t *option); + +/*! + * @brief Set Core LDO Regulator Voltage level in Active mode. + * + * @param base SPC peripheral base address. + * @param voltageLevel Specify the voltage level of CORE LDO Regulator in Active mode, please + refer to @ref spc_core_ldo_voltage_level_t. + * + * @note In active mode, the Core LDO voltage level should only be changed when the + * Core LDO is in normal drive strength. + * + * @note Update Core LDO voltage level will set Busy flag, + * this function return only when busy flag is cleared by hardware + * + * @retval kStatus_SPC_CORELDOVoltageSetFail The drive strength of Core LDO is not normal. + * @retval kStatus_Success Set Core LDO regulator voltage level in Active power mode successful. + */ +status_t SPC_SetActiveModeCoreLDORegulatorVoltageLevel(SPC_Type *base, spc_core_ldo_voltage_level_t voltageLevel); + +/*! + * @brief Gets CORE LDO Regulator Voltage level. + * + * This function returns the voltage level of CORE LDO Regulator in Active mode. + * + * @param base SPC peripheral base address. + * @return Voltage level of CORE LDO in type of @ref spc_core_ldo_voltage_level_t enumeration. + */ +static inline spc_core_ldo_voltage_level_t SPC_GetActiveModeCoreLDOVDDVoltageLevel(SPC_Type *base) +{ + return (spc_core_ldo_voltage_level_t)(uint32_t)((base->ACTIVE_CFG & SPC_ACTIVE_CFG_CORELDO_VDD_LVL_MASK) >> + SPC_ACTIVE_CFG_CORELDO_VDD_LVL_SHIFT); +} + +#if (defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) +/*! + * @brief Set Core LDO VDD Regulator Drive Strength in Active mode. + * + * @param base SPC peripheral base address. + * @param driveStrength Specify the drive strength of CORE LDO Regulator in Active mode, please + refer to @ref spc_core_ldo_drive_strength_t. + * + * @retval #kStatus_Success Set Core LDO regulator drive strength in Active power mode successful. + * @retval #kStatus_SPC_CORELDOLowDriveStrengthIgnore If any voltage detect enabled, + core_ldo's drive strength can not set to low. + * @retval #kStatus_SPC_BandgapModeWrong The selected bandgap mode is not allowed. + */ +status_t SPC_SetActiveModeCoreLDORegulatorDriveStrength(SPC_Type *base, spc_core_ldo_drive_strength_t driveStrength); + +/*! + * @brief Gets CORE LDO VDD Regulator Drive Strength in Active mode. + * + * @param base SPC peripheral base address. + * @return Drive Strength of CORE LDO regulator in Active mode, please refer to @ref spc_core_ldo_drive_strength_t. + */ +static inline spc_core_ldo_drive_strength_t SPC_GetActiveModeCoreLDODriveStrength(SPC_Type *base) +{ + return (spc_core_ldo_drive_strength_t)(uint32_t)((base->ACTIVE_CFG & SPC_ACTIVE_CFG_CORELDO_VDD_DS_MASK) >> + SPC_ACTIVE_CFG_CORELDO_VDD_DS_SHIFT); +} +#endif /* defined(FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS) && FSL_FEATURE_SPC_HAS_CORELDO_VDD_DS */ + +/*! + * @brief Configs CORE LDO Regulator in low power mode + * + * This function configs CORE LDO Regulator in Low Power mode. + * If CORE LDO VDD Drive Strength is set to Normal, the CORE LDO VDD regulator voltage + * level in Active mode must be equal to the voltage level in Low power mode. And the Bandgap + * must be programmed to select bandgap enabled. + * Core VDD voltage levels for the Core LDO low power regulator can only be changed when the CORE + * LDO Drive Strength set as Normal. + * + * @param base SPC peripheral base address. + * @param option Pointer to the spc_lowpower_mode_core_ldo_option_t structure. + * + * @retval #kStatus_Success Config Core LDO regulator in power mode successfully. + * @retval #kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * @retval #kStatus_SPC_CORELDOLowDriveStrengthIgnore Set driver strength to low will be ignored. + * @retval #kStatus_SPC_CORELDOVoltageSetFail. Fail to change Core LDO voltage level. + */ +status_t SPC_SetLowPowerModeCoreLDORegulatorConfig(SPC_Type *base, const spc_lowpower_mode_core_ldo_option_t *option); + +/*! + * @brief Set Core LDO VDD Regulator Voltage level in Low power mode. + * + * @note If CORE LDO's drive strength is set to Normal, the CORE LDO VDD regulator voltage in active mode and low power + * mode must be same. + * @note Voltage level for the CORE LDO in low power mode can only be changed when the CORE LDO Drive Strength set as + * Normal. + * + * @param base SPC peripheral base address. + * @param voltageLevel Voltage level of CORE LDO Regulator in Low power mode, please + refer to @ref spc_core_ldo_voltage_level_t. + * + * @retval #kStatus_SPC_CORELDOVoltageWrong Voltage level in active mode and low power mode is not same. + * @retval #kStatus_Success Set Core LDO regulator voltage level in Low power mode successful. + * @retval #kStatus_SPC_CORELDOVoltageSetFail Fail to update voltage level because drive strength is incorrect. + */ +status_t SPC_SetLowPowerModeCoreLDORegulatorVoltageLevel(SPC_Type *base, spc_core_ldo_voltage_level_t voltageLevel); + +/*! + * @brief Gets the CORE LDO VDD Regulator Voltage Level for Low Power modes. + * + * @param base SPC peripheral base address. + * @return The CORE LDO VDD Regulator's voltage level. + */ +static inline spc_core_ldo_voltage_level_t SPC_GetLowPowerCoreLDOVDDVoltageLevel(SPC_Type *base) +{ + return ((spc_core_ldo_voltage_level_t)(uint32_t)((base->LP_CFG & SPC_LP_CFG_CORELDO_VDD_LVL_MASK) >> + SPC_LP_CFG_CORELDO_VDD_LVL_SHIFT)); +} + +/*! + * @brief Set Core LDO VDD Regulator Drive Strength in Low power mode. + * + * @param base SPC peripheral base address. + * @param driveStrength Specify drive strength of CORE LDO in low power mode. + * + * @retval #kStatus_SPC_CORELDOLowDriveStrengthIgnore Some voltage detect enabled, CORE LDO's drive strength can not set + * as low. + * @retval #kStatus_Success Set Core LDO regulator drive strength in Low power mode successful. + * @retval #kStatus_SPC_BandgapModeWrong Bandgap is disabled when attempt to set CORE LDO work as normal drive strength. + */ +status_t SPC_SetLowPowerModeCoreLDORegulatorDriveStrength(SPC_Type *base, spc_core_ldo_drive_strength_t driveStrength); + +/*! + * @brief Gets CORE LDO VDD Drive Strength for Low Power modes. + * + * @param base SPC peripheral base address. + * @return The CORE LDO's VDD Drive Strength. + */ +static inline spc_core_ldo_drive_strength_t SPC_GetLowPowerCoreLDOVDDDriveStrength(SPC_Type *base) +{ + return (spc_core_ldo_drive_strength_t)(uint32_t)((base->LP_CFG & SPC_LP_CFG_CORELDO_VDD_DS_MASK) >> + SPC_LP_CFG_CORELDO_VDD_DS_SHIFT); +} + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) +/*! + * @name Low Level APIs To Set System LDO Regulator + * @{ + */ + +/*! + * @brief Enable/Disable System LDO regulator. + * + * @note The SYSTEM LDO enable bit is write-once. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable System LDO Regulator. + * true - Enable System LDO Regulator. + * false - Disable System LDO Regulator. + */ +static inline void SPC_EnableSystemLDORegulator(SPC_Type *base, bool enable) +{ + if (enable) + { + base->CNTRL |= SPC_CNTRL_SYSLDO_EN_MASK; + } + else + { + /* + * $Branch Coverage Justification$ + * If SYSTEM_LDO is disabled, may cause some unexpected issues. + */ + base->CNTRL &= ~SPC_CNTRL_SYSLDO_EN_MASK; + } +} + +/*! + * @brief Enable/Disable current sink feature of System LDO Regulator. + * + * @param base SPC peripheral base address. + * @param sink Enable/Disable current sink feature. + * true - Enable current sink feature of System LDO Regulator. + * false - Disable current sink feature of System LDO Regulator. + */ +static inline void SPC_EnableSystemLDOSinkFeature(SPC_Type *base, bool sink) +{ + if (sink) + { + base->SYSLDO_CFG |= SPC_SYSLDO_CFG_ISINKEN_MASK; + } + else + { + base->SYSLDO_CFG &= ~SPC_SYSLDO_CFG_ISINKEN_MASK; + } +} + +/*! + * @brief Configs System LDO VDD Regulator in Active mode. + * + * @note If System LDO VDD Drive Strength is set to Normal, the Bandgap mode in Active mode must be programmed + * to a value that enables the bandgap. + * @note If any voltage detects are kept enabled, configuration to set System LDO VDD drive strength to low will + * be ignored. + * @note If select System LDO VDD Regulator voltage level to Over Drive Voltage, the Drive Strength of System LDO VDD + * Regulator must be set to Normal otherwise the regulator Drive Strength will be forced to Normal. + * @note If select System LDO VDD Regulator voltage level to Over Drive Voltage, the High voltage detect must be + * disabled. Otherwise it will be fail to regulator to Over Drive Voltage. + * + * @param base SPC peripheral base address. + * @param option Pointer to the spc_active_mode_sys_ldo_option_t structure. + * + * @retval #kStatus_Success Config System LDO regulator in Active power mode successful. + * @retval #kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * @retval #kStatus_SPC_BandgapModeWrong The bandgap is not enabled before invoking this function. + * @retval #kStatus_SPC_SYSLDOOverDriveVoltageFail HVD of System VDD is not disable before setting to Over Drive + * voltage. + * @retval kStatus_SPC_SYSLDOLowDriveStrengthIgnore Set System LDO VDD regulator's driver strength to Low will be + * ignored. + */ +status_t SPC_SetActiveModeSystemLDORegulatorConfig(SPC_Type *base, const spc_active_mode_sys_ldo_option_t *option); + +/*! + * @brief Set System LDO Regulator voltage level in Active mode. + * + * @note The system LDO regulator can only operate at the overdrive voltage level for a limited amount of time for the + * life of chip. + * + * @param base SPC peripheral base address. + * @param voltageLevel Specify the voltage level of System LDO Regulator in Active mode. + * + * @retval #kStatus_Success Set System LDO Regulator voltage level in Active mode successfully. + * @retval #kStatus_SPC_SYSLDOOverDriveVoltageFail Must disable system LDO high voltage detector before specifing + * overdrive voltage. + */ +status_t SPC_SetActiveModeSystemLDORegulatorVoltageLevel(SPC_Type *base, spc_sys_ldo_voltage_level_t voltageLevel); + +/*! + * @brief Get System LDO Regulator voltage level in Active mode. + * + * @param base SPC peripheral base address. + * @return System LDO Regulator voltage level in Active mode, please refer to @ref spc_sys_ldo_voltage_level_t. + */ +static inline spc_sys_ldo_voltage_level_t SPC_GetActiveModeSystemLDORegulatorVoltageLevel(SPC_Type *base) +{ + return (spc_sys_ldo_voltage_level_t)(uint32_t)((base->ACTIVE_CFG & SPC_ACTIVE_CFG_SYSLDO_VDD_LVL_MASK) >> + SPC_ACTIVE_CFG_SYSLDO_VDD_LVL_SHIFT); +} + +/*! + * @brief Set System LDO Regulator Drive Strength in Active mode. + * + * @param base SPC peripheral base address. + * @param driveStrength Specify the drive strength of System LDO Regulator in Active mode. + * + * @retval #kStatus_Success Set System LDO Regulator drive strength in Active mode successfully. + * @retval #kStatus_SPC_SYSLDOLowDriveStrengthIgnore Attempt to specify low drive strength is ignored due to any + voltage detect feature is enabled in active mode. + * @retval #kStatus_SPC_BandgapModeWrong Bandgap mode in Active mode must be programmed to a value that enables + the bandgap if attempt to specify normal drive strength. + */ +status_t SPC_SetActiveModeSystemLDORegulatorDriveStrength(SPC_Type *base, spc_sys_ldo_drive_strength_t driveStrength); + +/*! + * @brief Get System LDO Regulator Drive Strength in Active mode. + * + * @param base SPC peripheral base address. + * @return System LDO regulator drive strength in Active mode, please refer to @ref spc_sys_ldo_drive_strength_t. + */ +static inline spc_sys_ldo_drive_strength_t SPC_GetActiveModeSystemLDORegulatorDriveStrength(SPC_Type *base) +{ + return (spc_sys_ldo_drive_strength_t)(uint32_t)((base->ACTIVE_CFG & SPC_ACTIVE_CFG_SYSLDO_VDD_DS_MASK) >> + SPC_ACTIVE_CFG_SYSLDO_VDD_DS_SHIFT); +} + +/*! + * @brief Configs System LDO regulator in low power modes. + * + * This function configs System LDO regulator in low power modes. + * If System LDO VDD Regulator Drive strength is set to normal, bandgap mode in low power + * mode must be programmed to a value that enables the Bandgap. + * If any High voltage detectors or Low Voltage detectors are kept enabled, configuration + * to set System LDO Regulator drive strength as Low will be ignored. + * + * @param base SPC peripheral base address. + * @param option Pointer to spc_lowpower_mode_sys_ldo_option_t structure. + * + * @retval #kStatus_Success Config System LDO regulator in Low Power Mode successfully. + * @retval #kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * @retval #kStatus_SPC_SYSLDOLowDriveStrengthIgnore Set driver strength to low will be ignored. + */ +status_t SPC_SetLowPowerModeSystemLDORegulatorConfig(SPC_Type *base, const spc_lowpower_mode_sys_ldo_option_t *option); + +/*! + * @brief Set System LDO Regulator drive strength in Low Power Mode. + * + * @param base SPC peripheral base address. + * @param driveStrength Specify the drive strength of System LDO Regulator in Low Power Mode. + * + * @retval #kStatus_Success Set System LDO Regulator drive strength in Low Power Mode successfully. + * @retval #kStatus_SPC_SYSLDOLowDriveStrengthIgnore Attempt to specify low drive strength is ignored due to any + voltage detect feature is enabled in low power mode. + * @retval #kStatus_SPC_BandgapModeWrong Bandgap mode in low power mode must be programmed to a value that enables + the bandgap if attempt to specify normal drive strength. + */ +status_t SPC_SetLowPowerModeSystemLDORegulatorDriveStrength(SPC_Type *base, spc_sys_ldo_drive_strength_t driveStrength); + +/*! + * @brief Get System LDO Regulator drive strength in Low Power Mode. + * + * @param base SPC peripheral base address. + * @return System LDO regulator drive strength in Low Power Mode, please refer to @ref spc_sys_ldo_drive_strength_t. + */ +static inline spc_sys_ldo_drive_strength_t SPC_GetLowPowerModeSystemLDORegulatorDriveStrength(SPC_Type *base) +{ + return (spc_sys_ldo_drive_strength_t)(uint32_t)((base->LP_CFG & SPC_LP_CFG_SYSLDO_VDD_DS_MASK) >> + SPC_LP_CFG_SYSLDO_VDD_DS_SHIFT); +} +/*! @} */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_SYS_LDO */ + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC) && FSL_FEATURE_MCX_SPC_HAS_DCDC) +/*! + * @name Low Level APIs To Set DCDC Regulator + * @{ + */ + +/*! + * @brief Enable/Disable DCDC Regulator. + * + * @note The DCDC enable bit is write-once, settings only reset after a POR, LVD, or HVD event. + * + * @param base SPC peripheral base address. + * @param enable Enable/Disable DCDC Regulator. + * true - Enable DCDC Regulator. + * false - Disable DCDC Regulator. + */ +static inline void SPC_EnableDCDCRegulator(SPC_Type *base, bool enable) +{ + if (enable) + { + base->CNTRL |= SPC_CNTRL_DCDC_EN_MASK; + } + else + { + /* + * $Branch Coverage Justification$ + * If DCDC is disabled, all RAMs data will powered off. + */ + base->CNTRL &= ~SPC_CNTRL_DCDC_EN_MASK; + } +} + +/*! + * @brief Config DCDC Burst options + * + * @param base SPC peripheral base address. + * @param config Pointer to spc_dcdc_burst_config_t structure. + */ +void SPC_SetDCDCBurstConfig(SPC_Type *base, spc_dcdc_burst_config_t *config); + +/*! + * @brief Trigger a software burst request to DCDC. + * + * @param base SPC peripheral base address. + */ +static inline void SPC_TriggerDCDCBurstRequest(SPC_Type *base) +{ + /* Blocking until previous DCDC burst completed. */ + while ((base->DCDC_BURST_CFG & SPC_DCDC_BURST_CFG_BURST_ACK_MASK) == 0UL) + { + } + + base->DCDC_BURST_CFG |= SPC_DCDC_BURST_CFG_BURST_REQ_MASK; +} + +/*! + * @brief Check if burst acknowlege flag is asserted. + * + * @param base SPC peripheral base address. + * + * @retval false DCDC burst not complete. + * @retval true DCDC burst complete. + */ +static inline bool SPC_CheckDCDCBurstAck(SPC_Type *base) +{ + return ((base->DCDC_BURST_CFG & SPC_DCDC_BURST_CFG_BURST_ACK_MASK) != 0UL); +} + +/*! + * @brief Clear DCDC busrt acknowledge flag. + * + * @param base SPC periphral base address. + */ +static inline void SPC_ClearDCDCBurstAckFlag(SPC_Type *base) +{ + base->DCDC_BURST_CFG |= SPC_DCDC_BURST_CFG_BURST_ACK_MASK; +} + +/*! + * @brief Set the count value of the reference clock to configure the period of DCDC not active. + * + * @note This function is only useful when DCDC's drive strength is set as pulse refresh. + * @note The pulse duration(time between on and off) is: reference clock period * (count + 2). + * + * @param base SPC peripheral base address. + * @param count The count value, 16 bit width. + */ +void SPC_SetDCDCRefreshCount(SPC_Type *base, uint16_t count); + +#if (defined(FSL_FEATURE_MCX_SPC_HAS_DCDC_CFG_BLEED_EN) && FSL_FEATURE_MCX_SPC_HAS_DCDC_CFG_BLEED_EN) +/*! + * @brief Enable a bleed resistor to discharge DCDC output when DCDC is disabled. + * + * @param base SPC peripheral base address. + * @param enable Used to enable/disable bleed resistor. + */ +static inline void SPC_EnableDCDCBleedResistor(SPC_Type *base, bool enable) +{ + if (enable) + { + base->DCDC_CFG |= SPC_DCDC_CFG_BLEED_EN_MASK; + } + else + { + base->DCDC_CFG &= ~SPC_DCDC_CFG_BLEED_EN_MASK; + } +} +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC_CFG_BLEED_EN */ + +/*! + * @brief Configs DCDC_CORE Regulator in Active mode. + * + * @note When changing the DCDC output voltage level, take care to change the CORE LDO voltage level. + * + * @param base SPC peripheral base address. + * @param option Pointer to the spc_active_mode_dcdc_option_t structure. + * + * @retval #kStatus_Success Config DCDC regulator in Active power mode successful. + * @retval #kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * @retval #kStatus_SPC_BandgapModeWrong Set DCDC_CORE Regulator drive strength to Normal, the Bandgap must be enabled. + */ +status_t SPC_SetActiveModeDCDCRegulatorConfig(SPC_Type *base, const spc_active_mode_dcdc_option_t *option); + +/*! + * @brief Set DCDC_CORE Regulator voltage level in Active mode. + * + * @note When changing the DCDC output voltage level, take care to change the CORE LDO voltage level. + * + * @param base SPC peripheral base address. + * @param voltageLevel Specify the DCDC_CORE Regulator voltage level, please refer to @ref spc_dcdc_voltage_level_t. + */ +static inline void SPC_SetActiveModeDCDCRegulatorVoltageLevel(SPC_Type *base, spc_dcdc_voltage_level_t voltageLevel) +{ + base->ACTIVE_CFG = + (base->ACTIVE_CFG & (~SPC_ACTIVE_CFG_DCDC_VDD_LVL_MASK)) | SPC_ACTIVE_CFG_DCDC_VDD_LVL(voltageLevel); +} + +/*! + * @brief Get DCDC_CORE Regulator voltage level in Active mode. + * + * @param base SPC peripheral base address. + * @return DCDC_CORE Regulator voltage level, please refer to @ref spc_dcdc_voltage_level_t. + */ +static inline spc_dcdc_voltage_level_t SPC_GetActiveModeDCDCRegulatorVoltageLevel(SPC_Type *base) +{ + return (spc_dcdc_voltage_level_t)((uint32_t)((base->ACTIVE_CFG & SPC_ACTIVE_CFG_DCDC_VDD_LVL_MASK) >> + SPC_ACTIVE_CFG_DCDC_VDD_LVL_SHIFT)); +} + +/*! + * @brief Set DCDC_CORE Regulator drive strength in Active mode. + * + * @note To set DCDC drive strength as Normal, the bandgap must be enabled. + * + * @param base SPC peripheral base address. + * @param driveStrength Specify the DCDC_CORE regulator drive strength, please refer to @ref spc_dcdc_drive_strength_t. + * + * @retval #kStatus_Success Set DCDC_CORE Regulator drive strength in Active mode successfully. + * @retval #kStatus_SPC_BandgapModeWrong Set DCDC_CORE Regulator drive strength to Normal, the Bandgap must be enabled. + */ +status_t SPC_SetActiveModeDCDCRegulatorDriveStrength(SPC_Type *base, spc_dcdc_drive_strength_t driveStrength); + +/*! + * @brief Get DCDC_CORE Regulator drive strength in Active mode. + * + * @param base SPC peripheral base address. + * @return DCDC_CORE Regulator drive strength, please refer to @ref spc_dcdc_drive_strength_t. + */ +static inline spc_dcdc_drive_strength_t SPC_GetActiveModeDCDCRegulatorDriveStrength(SPC_Type *base) +{ + return (spc_dcdc_drive_strength_t)((uint32_t)((base->ACTIVE_CFG & SPC_ACTIVE_CFG_DCDC_VDD_DS_MASK) >> + SPC_ACTIVE_CFG_DCDC_VDD_DS_SHIFT)); +} + +/*! + * @brief Configs DCDC_CORE Regulator in Low power modes. + * + * @note If DCDC_CORE Drive Strength is set to Normal, the Bandgap mode in Low Power mode must be programmed + * to a value that enables the Bandgap. + * @note In Deep Power Down mode, DCDC regulator is always turned off. + * + * @param base SPC peripheral base address. + * @param option Pointer to the spc_lowpower_mode_dcdc_option_t structure. + * + * @retval #kStatus_Success Config DCDC regulator in low power mode successfully. + * @retval #kStatus_SPC_Busy The SPC instance is busy to execute any type of power mode transition. + * @retval #kStatus_SPC_BandgapModeWrong The bandgap mode setting in Low Power mode is wrong. + */ +status_t SPC_SetLowPowerModeDCDCRegulatorConfig(SPC_Type *base, const spc_lowpower_mode_dcdc_option_t *option); + +/*! + * @brief Set DCDC_CORE Regulator drive strength in Low power mode. + * + * @note To set drive strength as normal, the bandgap must be enabled. + * + * @param base SPC peripheral base address. + * @param driveStrength Specify the DCDC_CORE Regulator drive strength, please refer to @ref spc_dcdc_drive_strength_t. + * + * @retval #kStatus_Success Set DCDC_CORE Regulator drive strength in Low power mode successfully. + * @retval #kStatus_SPC_BandgapModeWrong Set DCDC_CORE Regulator drive strength to Normal, the Bandgap must be enabled. + */ +status_t SPC_SetLowPowerModeDCDCRegulatorDriveStrength(SPC_Type *base, spc_dcdc_drive_strength_t driveStrength); + +/*! + * @brief Get DCDC_CORE Regulator drive strength in Low power mode. + * + * @param base SPC peripheral base address. + * @return DCDC_CORE Regulator drive strength, please refer to @ref spc_dcdc_drive_strength_t. + */ +static inline spc_dcdc_drive_strength_t SPC_GetLowPowerModeDCDCRegulatorDriveStrength(SPC_Type *base) +{ + return (spc_dcdc_drive_strength_t)((uint32_t)((base->LP_CFG & SPC_LP_CFG_DCDC_VDD_DS_MASK) >> + SPC_LP_CFG_DCDC_VDD_DS_SHIFT)); +} + +/*! + * @brief Set DCDC_CORE Regulator voltage level in Low power mode. + * + * @note To change DCDC level in Low-Power mode: + * 1. Configure LP_CFG[DCDC_VDD_LVL] to desired level; + * 2. Configure LP_CFG[DCDC_VDD_DS] to low driver strength; + * 3. Configure ACTIVE_CFG[DCDC_VDD_LVL] to same level programmed in #1. + * + * @note After invoking this function, the voltage level in active mode(wakeup from low power modes) also changed, + * if it is necessary, please invoke SPC_SetActiveModeDCDCRegulatorVoltageLevel() to change to desried voltage level. + * + * @param base SPC peripheral base address. + * @param voltageLevel Specify the DCDC_CORE Regulator voltage level, please refer to @ref spc_dcdc_voltage_level_t. + */ +static inline void SPC_SetLowPowerModeDCDCRegulatorVoltageLevel(SPC_Type *base, spc_dcdc_voltage_level_t voltageLevel) +{ + base->LP_CFG = (base->LP_CFG & (~SPC_LP_CFG_DCDC_VDD_LVL_MASK)) | SPC_LP_CFG_DCDC_VDD_LVL(voltageLevel); + (void)SPC_SetLowPowerModeDCDCRegulatorDriveStrength(base, kSPC_DCDC_LowDriveStrength); + SPC_SetActiveModeDCDCRegulatorVoltageLevel(base, voltageLevel); +} + +/*! + * @brief Get DCDC_CORE Regulator voltage level in Low power mode. + * + * @param base SPC peripheral base address. + * @return DCDC_CORE Regulator voltage level, please refer to @ref spc_dcdc_voltage_level_t. + */ +static inline spc_dcdc_voltage_level_t SPC_GetLowPowerModeDCDCRegulatorVoltageLevel(SPC_Type *base) +{ + return (spc_dcdc_voltage_level_t)((uint32_t)((base->LP_CFG & SPC_LP_CFG_DCDC_VDD_LVL_MASK) >> + SPC_LP_CFG_DCDC_VDD_LVL_SHIFT)); +} + +/*! @} */ +#endif /* FSL_FEATURE_MCX_SPC_HAS_DCDC */ + +#if defined(__cplusplus) +} +#endif /* __cplusplus */ + +/*! @} */ + +#endif /* FSL_SPC_H_ */ diff --git a/hw/bsp/mcx/family.c b/hw/bsp/mcx/family.c index 2b9c60beb..2dfefeb92 100644 --- a/hw/bsp/mcx/family.c +++ b/hw/bsp/mcx/family.c @@ -60,9 +60,14 @@ void USB0_IRQHandler(void) { void board_init(void) { + BOARD_InitPins(); + BOARD_InitBootClocks(); + + #ifdef XTAL0_CLK_HZ CLOCK_SetupExtClocking(XTAL0_CLK_HZ); + #endif #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer @@ -84,15 +89,7 @@ void board_init(void) { board_led_write(0); #ifdef NEOPIXEL_PIN - // Neopixel - static uint32_t pixelData[NEOPIXEL_NUMBER]; - IOCON_PinMuxSet(IOCON, NEOPIXEL_PORT, NEOPIXEL_PIN, IOCON_PIO_DIG_FUNC4_EN); - - sctpix_init(NEOPIXEL_TYPE); - sctpix_addCh(NEOPIXEL_CH, pixelData, NEOPIXEL_NUMBER); - sctpix_setPixel(NEOPIXEL_CH, 0, 0x100010); - sctpix_setPixel(NEOPIXEL_CH, 1, 0x100010); - sctpix_show(); + // No neo pixel support yet #endif // Button @@ -103,9 +100,6 @@ void board_init(void) { #endif #ifdef UART_DEV - // UART -// IOCON_PinMuxSet(IOCON, UART_RX_PINMUX); -// IOCON_PinMuxSet(IOCON, UART_TX_PINMUX); // Enable UART when debug log is on board_uart_init_clock(); @@ -115,6 +109,7 @@ void board_init(void) { uart_config.baudRate_Bps = CFG_BOARD_UART_BAUDRATE; uart_config.enableTx = true; uart_config.enableRx = true; + LPUART_Init(UART_DEV, &uart_config, 12000000u); #endif @@ -196,17 +191,6 @@ void board_init(void) { void board_led_write(bool state) { GPIO_PinWrite(LED_GPIO, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); - -#ifdef NEOPIXEL_PIN - if (state) { - sctpix_setPixel(NEOPIXEL_CH, 0, 0x100000); - sctpix_setPixel(NEOPIXEL_CH, 1, 0x101010); - } else { - sctpix_setPixel(NEOPIXEL_CH, 0, 0x001000); - sctpix_setPixel(NEOPIXEL_CH, 1, 0x000010); - } - sctpix_show(); -#endif } uint32_t board_button_read(void) { diff --git a/hw/bsp/mcx/family.cmake b/hw/bsp/mcx/family.cmake index 413c1b372..305497b79 100644 --- a/hw/bsp/mcx/family.cmake +++ b/hw/bsp/mcx/family.cmake @@ -10,6 +10,9 @@ include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) if (MCU_VARIANT STREQUAL "MCXA153") set(CMAKE_SYSTEM_CPU cortex-m33-nodsp-nofp CACHE INTERNAL "System Processor") set(FAMILY_MCUS MCXA15 CACHE INTERNAL "") +elseif (MCU_VARIANT STREQUAL "MCXA156") + set(CMAKE_SYSTEM_PROCESSOR cortex-m33 CACHE INTERNAL "System Processor") + set(FAMILY_MCUS MCXA15 CACHE INTERNAL "") elseif (MCU_VARIANT STREQUAL "MCXN947") set(CMAKE_SYSTEM_CPU cortex-m33 CACHE INTERNAL "System Processor") set(FAMILY_MCUS MCXN9 CACHE INTERNAL "") @@ -38,12 +41,14 @@ function(add_board_target BOARD_TARGET) endif() set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + add_library(${BOARD_TARGET} STATIC ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} # driver - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_gpio.c - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_common_arm.c - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_lpuart.c + ${SDK_DIR}/drivers/gpio/fsl_gpio.c + ${SDK_DIR}/drivers/common/fsl_common_arm.c + ${SDK_DIR}/drivers/lpuart/fsl_lpuart.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/drivers/spc/fsl_spc.c # mcu ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_clock.c ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_reset.c @@ -51,18 +56,27 @@ function(add_board_target BOARD_TARGET) ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMSIS_DIR}/CMSIS/Core/Include + ${SDK_DIR}/drivers/gpio/ + ${SDK_DIR}/drivers/lpuart + ${SDK_DIR}/drivers/common + ${SDK_DIR}/drivers/port + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/drivers/spc ${SDK_DIR}/devices/${MCU_VARIANT} ${SDK_DIR}/devices/${MCU_VARIANT}/drivers ) if (${FAMILY_MCUS} STREQUAL "MCXN9") + target_sources(${BOARD_TARGET} PRIVATE - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_lpflexcomm.c + ${SDK_DIR}/drivers/lpflexcomm/fsl_lpflexcomm.c + ) + + target_include_directories(${BOARD_TARGET} PUBLIC + ${SDK_DIR}/drivers/lpflexcomm ) elseif(${FAMILY_MCUS} STREQUAL "MCXA15") - target_sources(${BOARD_TARGET} PRIVATE - ${SDK_DIR}/devices/${MCU_VARIANT}/drivers/fsl_spc.c - ) + + endif() update_board(${BOARD_TARGET}) diff --git a/hw/bsp/mcx/family.mk b/hw/bsp/mcx/family.mk index 58149fb8d..676475cc9 100644 --- a/hw/bsp/mcx/family.mk +++ b/hw/bsp/mcx/family.mk @@ -35,18 +35,19 @@ SRC_C += \ $(SDK_DIR)/devices/$(MCU_VARIANT)/system_$(MCU_CORE).c \ $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_clock.c \ $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_reset.c \ - $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_gpio.c \ - $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_lpuart.c \ - $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_common_arm.c \ + ${SDK_DIR}/drivers/gpio/fsl_gpio.c \ + ${SDK_DIR}/drivers/lpuart/fsl_lpuart.c \ + ${SDK_DIR}/drivers/common/fsl_common_arm.c\ + hw/bsp/mcx/drivers/spc/fsl_spc.c # fsl_lpflexcomm for MCXN9 ifeq ($(MCU_VARIANT), MCXN947) - SRC_C += $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_lpflexcomm.c + SRC_C += ${SDK_DIR}/drivers/lpflexcomm/fsl_lpflexcomm.c endif # fsl_spc for MCXNA15 ifeq ($(MCU_VARIANT), MCXA153) - SRC_C += $(SDK_DIR)/devices/$(MCU_VARIANT)/drivers/fsl_spc.c + endif INC += \ @@ -54,5 +55,15 @@ INC += \ $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ $(TOP)/$(SDK_DIR)/devices/$(MCU_VARIANT) \ $(TOP)/$(SDK_DIR)/devices/$(MCU_VARIANT)/drivers \ + $(TOP)/$(SDK_DIR)/drivers/ \ + $(TOP)/$(SDK_DIR)/drivers/lpuart \ + $(TOP)/$(SDK_DIR)/drivers/lpflexcomm \ + $(TOP)/$(SDK_DIR)/drivers/common\ + $(TOP)/$(SDK_DIR)/drivers/gpio\ + $(TOP)/$(SDK_DIR)/drivers/port\ + $(TOP)/hw/bsp/mcx/drivers/spc + + + SRC_S += $(SDK_DIR)/devices/$(MCU_VARIANT)/gcc/startup_$(MCU_CORE).S diff --git a/tools/get_deps.py b/tools/get_deps.py index ba9dc23ce..f5164f31c 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -55,8 +55,8 @@ deps_optional = { 'hw/mcu/nxp/lpcopen': ['https://github.com/hathach/nxp_lpcopen.git', 'b41cf930e65c734d8ec6de04f1d57d46787c76ae', 'lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43'], - 'hw/mcu/nxp/mcux-sdk': ['https://github.com/hathach/mcux-sdk.git', - '144f1eb7ea8c06512e12f12b27383601c0272410', + 'hw/mcu/nxp/mcux-sdk': ['https://github.com/nxp-mcuxpresso/mcux-sdk', + 'a1bdae309a14ec95a4f64a96d3315a4f89c397c6', 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'], 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/hathach/Pico-PIO-USB.git', '810653f66adadba3e0e4b4b56d5167ac4f7fdbf7', @@ -243,11 +243,13 @@ def get_a_dep(d): p.mkdir(parents=True) run_cmd(f"{git_cmd} init") run_cmd(f"{git_cmd} remote add origin {url}") + head = None + else: + # Check if commit is already fetched + result = run_cmd(f"{git_cmd} rev-parse HEAD") + head = result.stdout.decode("utf-8").splitlines()[0] + run_cmd(f"{git_cmd} reset --hard") - # Check if commit is already fetched - result = run_cmd(f"{git_cmd} rev-parse HEAD") - head = result.stdout.decode("utf-8").splitlines()[0] - run_cmd(f"{git_cmd} reset --hard") if commit != head: run_cmd(f"{git_cmd} fetch --depth 1 origin {commit}") run_cmd(f"{git_cmd} checkout FETCH_HEAD") From 2c1414b4c18518a179560a097aada40609303693 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 28 Apr 2025 12:59:59 +0700 Subject: [PATCH 156/382] usbh: add roothub debounncing flag to ignore attach/remove event on the roothub that is currently doing debouncing delay --- src/host/usbh.c | 22 ++++++++++++++++++---- src/portable/synopsys/dwc2/hcd_dwc2.c | 19 +++---------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 8469aee83..8852bdda4 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -275,6 +275,7 @@ typedef struct { typedef struct { uint8_t controller_id; // controller ID uint8_t enumerating_daddr; // device address of the device being enumerated + uint8_t attach_debouncing_bm; // bitmask for roothub port attach debouncing tuh_bus_info_t dev0_bus; // bus info for dev0 in enumeration usbh_ctrl_xfer_info_t ctrl_xfer_info; // control transfer } usbh_data_t; @@ -349,7 +350,7 @@ bool tuh_rhport_is_active(uint8_t rhport) { bool tuh_rhport_reset_bus(uint8_t rhport, bool active) { TU_VERIFY(tuh_rhport_is_active(rhport)); - if ( active ) { + if (active) { hcd_port_reset(rhport); } else { hcd_port_reset_end(rhport); @@ -1021,10 +1022,18 @@ bool tuh_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info) { TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) { switch (event->event_id) { case HCD_EVENT_DEVICE_ATTACH: - - break; - case HCD_EVENT_DEVICE_REMOVE: + // Attach debouncing on roothub: skip attach/remove while debouncing delay + if (event->connection.hub_addr == 0) { + if (tu_bit_test(_usbh_data.attach_debouncing_bm, event->rhport)) { + return; + } + + if (event->event_id == HCD_EVENT_DEVICE_ATTACH) { + // No debouncing, set flag if attach event + _usbh_data.attach_debouncing_bm |= TU_BIT(event->rhport); + } + } break; default: break; @@ -1406,6 +1415,11 @@ static bool enum_new_device(hcd_event_t* event) { // wait until device connection is stable TODO non blocking tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); + // clear roothub debouncing delay + if (dev0_bus->hub_addr == 0) { + _usbh_data.attach_debouncing_bm &= (uint8_t) ~TU_BIT(dev0_bus->rhport); + } + if (dev0_bus->hub_addr == 0) { // connected directly to roothub // USB bus not active and frame number is not available yet. diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 7c29a03cf..2de15068a 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -107,7 +107,6 @@ typedef struct { typedef struct { hcd_xfer_t xfer[DWC2_CHANNEL_COUNT_MAX]; hcd_endpoint_t edpt[CFG_TUH_DWC2_ENDPOINT_MAX]; - bool attach_debounce; // if true: wait for the debounce delay before issuing new attach events } hcd_data_t; hcd_data_t _hcd_data; @@ -423,11 +422,6 @@ uint32_t hcd_frame_number(uint8_t rhport) { // Get the current connect status of roothub port bool hcd_port_connect_status(uint8_t rhport) { - // this is called from enum_new_device() - after the debouncing delays - if (_hcd_data.attach_debounce) { - _hcd_data.attach_debounce = false; // allow new attach events again - } - dwc2_regs_t* dwc2 = DWC2_REG(rhport); return dwc2->hprt & HPRT_CONN_STATUS; } @@ -1328,10 +1322,7 @@ static void handle_hprt_irq(uint8_t rhport, bool in_isr) { hprt |= HPRT_CONN_DETECT; if (hprt_bm.conn_status) { - if (!_hcd_data.attach_debounce) { - _hcd_data.attach_debounce = true; // block new attach events until the debounce delay is over - hcd_event_device_attach(rhport, in_isr); - } + hcd_event_device_attach(rhport, in_isr); } } @@ -1398,12 +1389,8 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { // Device disconnected dwc2->gintsts = GINTSTS_DISCINT; - // ignore device removal if attach debounce is active - // it will evaluate the port status after the debounce delay - if (!_hcd_data.attach_debounce) { - if (!(dwc2->hprt & HPRT_CONN_STATUS)) { - hcd_event_device_remove(rhport, in_isr); - } + if (!(dwc2->hprt & HPRT_CONN_STATUS)) { + hcd_event_device_remove(rhport, in_isr); } } From 42d4f7c81e65a2d39b8e108b1ef8ed58945b7617 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 28 Apr 2025 15:10:03 +0700 Subject: [PATCH 157/382] remove the old attach duplicated logic, debouncing skip should take care of it. --- src/host/usbh.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 8852bdda4..6f875c80b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -513,28 +513,19 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { case HCD_EVENT_DEVICE_ATTACH: // due to the shared control buffer, we must fully complete enumerating one device first. // TODO better to have an separated queue for newly attached devices - if (_usbh_data.enumerating_daddr != TUSB_INDEX_INVALID_8) { - if (event.rhport == _usbh_data.dev0_bus.rhport && - event.connection.hub_addr == _usbh_data.dev0_bus.hub_addr && event.connection.hub_port == _usbh_data.dev0_bus.hub_port) { - // Some device can cause multiple duplicated attach events - // drop current enumerating and start over for a proper port reset - // abort/cancel current enumeration and start new one - TU_LOG1("[%u:] USBH Device Attach (duplicated)\r\n", event.rhport); - tuh_edpt_abort_xfer(0, 0); - enum_new_device(&event); - } else { - TU_LOG_USBH("[%u:] USBH Defer Attach until current enumeration complete\r\n", event.rhport); - bool is_empty = osal_queue_empty(_usbh_q); - queue_event(&event, in_isr); - - if (is_empty) { - // Exit if this is the only event in the queue, otherwise we may loop forever - return; - } - } - } else { + if (_usbh_data.enumerating_daddr == TUSB_INDEX_INVALID_8) { + // New device attached and we are ready TU_LOG1("[%u:] USBH Device Attach\r\n", event.rhport); + _usbh_data.enumerating_daddr = 0; // enumerate new device with address 0 enum_new_device(&event); + } else { + // currently enumerating another device + TU_LOG_USBH("[%u:] USBH Defer Attach until current enumeration complete\r\n", event.rhport); + const bool is_empty = osal_queue_empty(_usbh_q); + queue_event(&event, in_isr); + if (is_empty) { + return; // Exit if this is the only event in the queue, otherwise we loop forever + } } break; @@ -1410,8 +1401,6 @@ static bool enum_new_device(hcd_event_t* event) { dev0_bus->hub_addr = event->connection.hub_addr; dev0_bus->hub_port = event->connection.hub_port; - _usbh_data.enumerating_daddr = 0; - // wait until device connection is stable TODO non blocking tusb_time_delay_ms_api(ENUM_DEBOUNCING_DELAY_MS); From 538684ac621f2ba0ad17865e2d5670089bfbb296 Mon Sep 17 00:00:00 2001 From: Eli Hughes Date: Mon, 28 Apr 2025 07:58:09 -0400 Subject: [PATCH 158/382] - spelling fixes to pass ci - added mca156 the list in boards.rst. - Fixup to family.cmake for mcxa156 to pass ci --- docs/reference/boards.rst | 1 + hw/bsp/mcx/drivers/spc/fsl_spc.c | 12 ++++++------ hw/bsp/mcx/drivers/spc/fsl_spc.h | 18 +++++++++--------- hw/bsp/mcx/family.cmake | 2 +- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 4739467bc..5786b2182 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -165,6 +165,7 @@ lpcxpresso55s28 LPCXpresso55s28 lpc55 ht lpcxpresso55s69 LPCXpresso55s69 lpc55 https://www.nxp.com/design/design-center/software/development-software/mcuxpresso-software-and-tools-/lpcxpresso-boards/lpcxpresso55s69-development-board:LPC55S69-EVK mcu_link MCU Link lpc55 https://www.nxp.com/design/design-center/software/development-software/mcuxpresso-software-and-tools-/mcu-link-debug-probe:MCU-LINK frdm_mcxa153 Freedom MCXA153 mcx https://www.nxp.com/design/design-center/development-boards-and-designs/FRDM-MCXA153 +frdm_mcxa156 Freedom MCXA156 mcx https://www.nxp.com/design/design-center/development-boards-and-designs/FRDM-MCXA156 frdm_mcxn947 Freedom MCXN947 mcx https://www.nxp.com/design/design-center/development-boards-and-designs/FRDM-MCXN947 mcxn947brk MCXN947 Breakout mcx n/a ================== ========================================= ============= ========================================================================================================================================================================= ====== diff --git a/hw/bsp/mcx/drivers/spc/fsl_spc.c b/hw/bsp/mcx/drivers/spc/fsl_spc.c index c6a9b2932..b39a406cb 100644 --- a/hw/bsp/mcx/drivers/spc/fsl_spc.c +++ b/hw/bsp/mcx/drivers/spc/fsl_spc.c @@ -161,7 +161,7 @@ void SPC_SetSRAMOperateVoltage(SPC_Type *base, const spc_sram_voltage_config_t * * @note To disable bandgap in Active mode: * 1. Disable all LVD's and HVD's in active mode; * 2. Disable Glitch detect; - * 3. Configrue LDO's and DCDC to low drive strength in active mode; + * 3. Configure LDO's and DCDC to low drive strength in active mode; * 4. Invoke this function to disable bandgap in active mode; * otherwise the error status will be reported. * @@ -1115,7 +1115,7 @@ status_t SPC_SetActiveModeSystemLDORegulatorConfig(SPC_Type *base, const spc_act return kStatus_SPC_BandgapModeWrong; } - /* 3. Must disable system LDO high voltage detector before specifing overdrive voltage. */ + /* 3. Must disable system LDO high voltage detector before specifying overdrive voltage. */ if ((option->SysLDOVoltage == kSPC_SysLDO_OverDriveVoltage) && ((SPC_GetActiveModeVoltageDetectStatus(base) & SPC_ACTIVE_CFG_SYS_HVDE_MASK) != 0UL)) { @@ -1138,14 +1138,14 @@ status_t SPC_SetActiveModeSystemLDORegulatorConfig(SPC_Type *base, const spc_act * param voltageLevel Specify the voltage level of System LDO Regulator in Active mode. * * retval #kStatus_Success Set System LDO Regulator voltage level in Active mode successfully. - * retval #kStatus_SPC_SYSLDOOverDriveVoltageFail Must disable system LDO high voltage detector before specifing + * retval #kStatus_SPC_SYSLDOOverDriveVoltageFail Must disable system LDO high voltage detector before specifying * overdrive voltage. */ status_t SPC_SetActiveModeSystemLDORegulatorVoltageLevel(SPC_Type *base, spc_sys_ldo_voltage_level_t voltageLevel) { if (voltageLevel == kSPC_SysLDO_OverDriveVoltage) { - /* Must disable system LDO high voltage detector before specifing overdrive voltage. */ + /* Must disable system LDO high voltage detector before specifying overdrive voltage. */ if ((SPC_GetActiveModeVoltageDetectStatus(base) & SPC_ACTIVE_CFG_SYS_HVDE_MASK) != 0UL) { return kStatus_SPC_SYSLDOOverDriveVoltageFail; @@ -1490,7 +1490,7 @@ void SPC_SetDCDCRefreshCount(SPC_Type *base, uint16_t count) * * * @note Some hardware restrictions not covered, application should be aware of this and follow this hardware - * restrictions otherwise some unkown issue may occur: + * restrictions otherwise some unknown issue may occur: * 1. If Core LDO's drive strength are set to same value in both Active mode and low power mode, * the voltage level should also set to same value. * 2. When switching Core LDO's drive strength from low to normal, ensure the LDO_CORE high voltage level is set @@ -1538,7 +1538,7 @@ status_t SPC_SetActiveModeRegulatorsConfig(SPC_Type *base, const spc_active_mode } #if (defined(FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) && FSL_FEATURE_MCX_SPC_HAS_SYS_LDO) - /* 2. Must disable system LDO high voltage detector before specifing SysLDO to overdrive voltage */ + /* 2. Must disable system LDO high voltage detector before specifying SysLDO to overdrive voltage */ if (((activeModeVDValue & SPC_ACTIVE_CFG_SYS_HVDE_MASK) != 0UL) && (config->SysLDOOption.SysLDOVoltage == kSPC_SysLDO_OverDriveVoltage)) { diff --git a/hw/bsp/mcx/drivers/spc/fsl_spc.h b/hw/bsp/mcx/drivers/spc/fsl_spc.h index 52cb71c24..d3e75fbcb 100644 --- a/hw/bsp/mcx/drivers/spc/fsl_spc.h +++ b/hw/bsp/mcx/drivers/spc/fsl_spc.h @@ -128,7 +128,7 @@ enum _spc_analog_module_control }; /*! - * @brief The enumeration of spc power domain, the connected power domain is chip specfic, please refer to chip's RM + * @brief The enumeration of spc power domain, the connected power domain is chip specific, please refer to chip's RM * for details. */ typedef enum _spc_power_domain_id @@ -153,8 +153,8 @@ typedef enum _spc_power_domain_low_power_mode */ typedef enum _spc_lowPower_request_pin_polarity { - kSPC_HighTruePolarity = 0x0U, /*!< Control the High Polarity of the Low Power Reqest Pin. */ - kSPC_LowTruePolarity = 0x1U, /*!< Control the Low Polarity of the Low Power Reqest Pin. */ + kSPC_HighTruePolarity = 0x0U, /*!< Control the High Polarity of the Low Power Request Pin. */ + kSPC_LowTruePolarity = 0x1U, /*!< Control the Low Polarity of the Low Power Request Pin. */ } spc_lowpower_request_pin_polarity_t; /*! @@ -197,7 +197,7 @@ typedef enum _spc_dcdc_voltage_level /*! * @brief DCDC regulator Drive Strength enumeration in Active mode or Low Power Mode. * - * @note Different drive strength differ in these DCDC characterstics: + * @note Different drive strength differ in these DCDC characteristics: * Maximum load current * Quiescent current * Transient response. @@ -901,7 +901,7 @@ static inline uint32_t SPC_GetActiveModeVoltageDetectStatus(SPC_Type *base) * @note To disable bandgap in Active mode: * 1. Disable all LVD's and HVD's in active mode; * 2. Disable Glitch detect; - * 3. Configrue LDO's and DCDC to low drive strength in active mode; + * 3. Configure LDO's and DCDC to low drive strength in active mode; * 4. Invoke this function to disable bandgap in active mode; * otherwise the error status will be reported. * @@ -962,7 +962,7 @@ static inline void SPC_SetActiveModeVoltageTrimDelay(SPC_Type *base, uint16_t de * * * @note Some hardware restrictions not covered, application should be aware of this and follow this hardware - * restrictions otherwise some unkown issue may occur: + * restrictions otherwise some unknown issue may occur: * 1. If Core LDO's drive strength are set to same value in both Active mode and low power mode, * the voltage level should also set to same value. * 2. When switching Core LDO's drive strength from low to normal, ensure the LDO_CORE high voltage level is set @@ -1275,7 +1275,7 @@ static inline void SPC_SetLowPowerWakeUpDelay(SPC_Type *base, uint16_t delay) * parameters do not satisfy hardware restrictions the specific error will be reported. * * @note Some hardware restrictions not covered, application should be aware of this and follow this hardware - * restrictions otherwise some unkown issue may occur: + * restrictions otherwise some unknown issue may occur: * 1. If Core LDO's drive strength are set to same value in both Active mode and low power mode, * the voltage level should also set to same value. * 2. When switching Core LDO's drive strength from low to normal, ensure the LDO_CORE high voltage level is set @@ -2084,7 +2084,7 @@ status_t SPC_SetActiveModeSystemLDORegulatorConfig(SPC_Type *base, const spc_act * @param voltageLevel Specify the voltage level of System LDO Regulator in Active mode. * * @retval #kStatus_Success Set System LDO Regulator voltage level in Active mode successfully. - * @retval #kStatus_SPC_SYSLDOOverDriveVoltageFail Must disable system LDO high voltage detector before specifing + * @retval #kStatus_SPC_SYSLDOOverDriveVoltageFail Must disable system LDO high voltage detector before specifying * overdrive voltage. */ status_t SPC_SetActiveModeSystemLDORegulatorVoltageLevel(SPC_Type *base, spc_sys_ldo_voltage_level_t voltageLevel); @@ -2229,7 +2229,7 @@ static inline void SPC_TriggerDCDCBurstRequest(SPC_Type *base) } /*! - * @brief Check if burst acknowlege flag is asserted. + * @brief Check if burst acknowledge flag is asserted. * * @param base SPC peripheral base address. * diff --git a/hw/bsp/mcx/family.cmake b/hw/bsp/mcx/family.cmake index 305497b79..f857ed31a 100644 --- a/hw/bsp/mcx/family.cmake +++ b/hw/bsp/mcx/family.cmake @@ -11,7 +11,7 @@ if (MCU_VARIANT STREQUAL "MCXA153") set(CMAKE_SYSTEM_CPU cortex-m33-nodsp-nofp CACHE INTERNAL "System Processor") set(FAMILY_MCUS MCXA15 CACHE INTERNAL "") elseif (MCU_VARIANT STREQUAL "MCXA156") - set(CMAKE_SYSTEM_PROCESSOR cortex-m33 CACHE INTERNAL "System Processor") + set(CMAKE_SYSTEM_CPU cortex-m33 CACHE INTERNAL "System Processor") set(FAMILY_MCUS MCXA15 CACHE INTERNAL "") elseif (MCU_VARIANT STREQUAL "MCXN947") set(CMAKE_SYSTEM_CPU cortex-m33 CACHE INTERNAL "System Processor") From fc43eeddf2b3d045431d56cc50bb0e2d6fdf5b98 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Apr 2025 10:11:20 +0700 Subject: [PATCH 159/382] attach debouncing fixed issue with port1 highspeed on imxrt --- .idea/debugServers/rt1060.xml | 2 +- .idea/debugServers/rt1064.xml | 2 +- .idea/debugServers/sam21.xml | 2 +- .idea/debugServers/sam51.xml | 2 +- .idea/debugServers/stm32f769.xml | 4 ++-- .idea/debugServers/stm32h563.xml | 2 +- .idea/debugServers/stm32h743.xml | 2 +- src/portable/chipidea/ci_hs/hcd_ci_hs.c | 6 ------ 8 files changed, 8 insertions(+), 14 deletions(-) diff --git a/.idea/debugServers/rt1060.xml b/.idea/debugServers/rt1060.xml index 3325cc81f..cbd295b4e 100644 --- a/.idea/debugServers/rt1060.xml +++ b/.idea/debugServers/rt1060.xml @@ -5,7 +5,7 @@ - + diff --git a/.idea/debugServers/rt1064.xml b/.idea/debugServers/rt1064.xml index 4dc38ef63..691066f9d 100644 --- a/.idea/debugServers/rt1064.xml +++ b/.idea/debugServers/rt1064.xml @@ -5,7 +5,7 @@ - + diff --git a/.idea/debugServers/sam21.xml b/.idea/debugServers/sam21.xml index d8763b33b..3f6735bd1 100644 --- a/.idea/debugServers/sam21.xml +++ b/.idea/debugServers/sam21.xml @@ -5,7 +5,7 @@ - + diff --git a/.idea/debugServers/sam51.xml b/.idea/debugServers/sam51.xml index 0d15ff856..99a92c174 100644 --- a/.idea/debugServers/sam51.xml +++ b/.idea/debugServers/sam51.xml @@ -5,7 +5,7 @@ - + diff --git a/.idea/debugServers/stm32f769.xml b/.idea/debugServers/stm32f769.xml index 2fb322a0f..22a452218 100644 --- a/.idea/debugServers/stm32f769.xml +++ b/.idea/debugServers/stm32f769.xml @@ -1,11 +1,11 @@ - + - + diff --git a/.idea/debugServers/stm32h563.xml b/.idea/debugServers/stm32h563.xml index 9bf6db6e9..637839314 100644 --- a/.idea/debugServers/stm32h563.xml +++ b/.idea/debugServers/stm32h563.xml @@ -5,7 +5,7 @@ - + diff --git a/.idea/debugServers/stm32h743.xml b/.idea/debugServers/stm32h743.xml index 63680b78c..b04e4a708 100644 --- a/.idea/debugServers/stm32h743.xml +++ b/.idea/debugServers/stm32h743.xml @@ -5,7 +5,7 @@ - + diff --git a/src/portable/chipidea/ci_hs/hcd_ci_hs.c b/src/portable/chipidea/ci_hs/hcd_ci_hs.c index 22eb22690..b5324a754 100644 --- a/src/portable/chipidea/ci_hs/hcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/hcd_ci_hs.c @@ -93,12 +93,6 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { hcd_reg->USBMODE = USBMODE_CM_HOST; #endif - // FIXME force full speed, still have issue with Highspeed enumeration - // probably due to physical connection bouncing when plug/unplug - // 1. Have issue when plug/unplug devices, maybe the port is not reset properly - // 2. Also does not seems to detect disconnection - hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED; - return ehci_init(rhport, (uint32_t) &hcd_reg->CAPLENGTH, (uint32_t) &hcd_reg->USBCMD); } From e7d4b5c9e718b1e72df8aadb884d2f36ab9d158c Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Apr 2025 17:04:10 +0700 Subject: [PATCH 160/382] add enum for set addr recovery --- .idea/cmake.xml | 6 +++--- .idea/debugServers/rt1064.xml | 4 ++-- src/host/usbh.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.idea/cmake.xml b/.idea/cmake.xml index b8383a5ff..dd219bc77 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -12,7 +12,7 @@ - + @@ -94,7 +94,8 @@ - + + @@ -166,7 +167,6 @@ - \ No newline at end of file diff --git a/.idea/debugServers/rt1064.xml b/.idea/debugServers/rt1064.xml index 691066f9d..b908b59e2 100644 --- a/.idea/debugServers/rt1064.xml +++ b/.idea/debugServers/rt1064.xml @@ -1,11 +1,11 @@ - + - + diff --git a/src/host/usbh.c b/src/host/usbh.c index 6f875c80b..fbb61e10e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1363,6 +1363,7 @@ enum { // USB 2.0 specs 7.1.7 for timing ENUM_RESET_ROOT_DELAY_MS = 50, // T(DRSTr) minimum 50 ms for reset from root port ENUM_RESET_HUB_DELAY_MS = 20, // T(DRST) 10-20 ms for hub reset ENUM_RESET_RECOVERY_DELAY_MS = 10, // T(RSTRCY) minimum 10 ms for reset recovery + ENUM_SET_ADDRESS_RECOVERY_DELAY_MS = 2, // USB 2.0 Spec 9.2.6.3 min is 2 ms }; enum { @@ -1573,8 +1574,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { } case ENUM_GET_DEVICE_DESC: { - // Allow 2ms for address recovery time, Ref USB Spec 9.2.6.3 - tusb_time_delay_ms_api(2); + tusb_time_delay_ms_api(ENUM_SET_ADDRESS_RECOVERY_DELAY_MS); // set address recovery const uint8_t new_addr = (uint8_t) tu_le16toh(xfer->setup->wValue); usbh_device_t* new_dev = get_device(new_addr); From 2abd3c54c4141e5e6e0bd4fea38849cb150fb161 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Apr 2025 20:49:47 +0700 Subject: [PATCH 161/382] define hcd_devtree_info_t forr backward compatible --- src/host/usbh.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/host/usbh.h b/src/host/usbh.h index 6f09f0c80..6f34d8bb3 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -86,6 +86,9 @@ typedef struct { uint8_t speed; } tuh_bus_info_t; +// backward compatibility for hcd_devtree_info_t, maybe removed in the future +#define hcd_devtree_info_t tuh_bus_info_t +#define hcd_devtree_get_info(_daddr, _bus_info) tuh_bus_info_get(_daddr, _bus_info) // ConfigID for tuh_configure() enum { From d221d55b080a818bdf9d43317660e22fd0a832c5 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 29 Apr 2025 21:41:34 +0700 Subject: [PATCH 162/382] fix pre-commmit --- hw/bsp/lpc51/family.mk | 2 +- hw/bsp/lpc55/family.mk | 2 -- hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h | 2 +- hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c | 2 +- hw/bsp/mcx/boards/frdm_mcxa156/clock_config.h | 3 +-- hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.c | 2 +- hw/bsp/mcx/drivers/spc/fsl_spc.c | 4 ++-- hw/bsp/mcx/drivers/spc/fsl_spc.h | 2 +- 8 files changed, 8 insertions(+), 11 deletions(-) diff --git a/hw/bsp/lpc51/family.mk b/hw/bsp/lpc51/family.mk index f37360a71..91d1261cb 100644 --- a/hw/bsp/lpc51/family.mk +++ b/hw/bsp/lpc51/family.mk @@ -40,7 +40,7 @@ INC += \ $(TOP)/$(SDK_DIR)/drivers/flexcomm/usart \ $(TOP)/$(SDK_DIR)/drivers/lpc_iocon \ $(TOP)/$(SDK_DIR)/drivers/lpc_gpio - + SRC_S += $(MCU_DIR)/gcc/startup_$(MCU).S LIBS += $(TOP)/$(MCU_DIR)/gcc/libpower.a diff --git a/hw/bsp/lpc55/family.mk b/hw/bsp/lpc55/family.mk index 85b9a2cc9..b83942c87 100644 --- a/hw/bsp/lpc55/family.mk +++ b/hw/bsp/lpc55/family.mk @@ -62,5 +62,3 @@ INC += \ $(TOP)/$(SDK_DIR)/drivers/sctimer SRC_S += $(MCU_DIR)/gcc/startup_$(MCU_CORE).S - - diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h b/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h index 079d0d312..aae811052 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h +++ b/hw/bsp/mcx/boards/frdm_mcxa153/clock_config.h @@ -4,7 +4,7 @@ * * SPDX-License-Identifier: BSD-3-Clause */ - + /*********************************************************************************************************************** * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. diff --git a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c b/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c index fce756e72..47709951b 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c +++ b/hw/bsp/mcx/boards/frdm_mcxa153/pin_mux.c @@ -67,7 +67,7 @@ void BOARD_InitPins(void) /* PORT3 peripheral is released from reset */ RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn); - + /* Write to PORT0: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GatePORT0); /* LPUART0 peripheral is released from reset */ diff --git a/hw/bsp/mcx/boards/frdm_mcxa156/clock_config.h b/hw/bsp/mcx/boards/frdm_mcxa156/clock_config.h index db80b79f3..3f5dfefda 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa156/clock_config.h +++ b/hw/bsp/mcx/boards/frdm_mcxa156/clock_config.h @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: BSD-3-Clause */ - + /*********************************************************************************************************************** * This file was generated by the MCUXpresso Config Tools. Any manual edits made to this file * will be overwritten if the respective MCUXpresso Config Tools is used to update this file. @@ -167,4 +167,3 @@ void BOARD_BootClockFRO96M(void); #endif /* __cplusplus*/ #endif /* _CLOCK_CONFIG_H_ */ - diff --git a/hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.c b/hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.c index 317c311b5..de35103a6 100644 --- a/hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.c +++ b/hw/bsp/mcx/boards/frdm_mcxa156/pin_mux.c @@ -81,7 +81,7 @@ void BOARD_InitPins(void) RESET_ReleasePeripheralReset(kGPIO0_RST_SHIFT_RSTn); /* PORT3 peripheral is released from reset */ RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn); - + /* PORT0: Peripheral clock is enabled */ CLOCK_EnableClock(kCLOCK_GatePORT0); /* LPUART0 peripheral is released from reset */ diff --git a/hw/bsp/mcx/drivers/spc/fsl_spc.c b/hw/bsp/mcx/drivers/spc/fsl_spc.c index b39a406cb..b16ca5fc5 100644 --- a/hw/bsp/mcx/drivers/spc/fsl_spc.c +++ b/hw/bsp/mcx/drivers/spc/fsl_spc.c @@ -454,9 +454,9 @@ status_t SPC_EnableLowPowerModeCoreLowVoltageDetect(SPC_Type *base, bool enable) * * This function selects the system VDD low-voltage level. Changing system VDD low-voltage level * must be done after disabling the System VDD low voltage reset and interrupt. - * + * * @deprecated In latest RM, reserved for all devices, will removed in next release. - * + * * param base SPC peripheral base address. * param level System VDD Low-Voltage level selection. See @ref spc_low_voltage_level_select_t for details. */ diff --git a/hw/bsp/mcx/drivers/spc/fsl_spc.h b/hw/bsp/mcx/drivers/spc/fsl_spc.h index d3e75fbcb..69a001098 100644 --- a/hw/bsp/mcx/drivers/spc/fsl_spc.h +++ b/hw/bsp/mcx/drivers/spc/fsl_spc.h @@ -206,7 +206,7 @@ typedef enum _spc_dcdc_drive_strength { kSPC_DCDC_PulseRefreshMode = 0x0U, /*!< DCDC_CORE Regulator Drive Strength set to Pulse Refresh Mode, * This enum member is only useful for Low Power Mode config, please - * note that pluse refresh mode is invalid in SLEEP mode. + * note that pulse refresh mode is invalid in SLEEP mode. */ kSPC_DCDC_LowDriveStrength = 0x1U, /*!< DCDC_CORE regulator Drive Strength set to low. */ kSPC_DCDC_NormalDriveStrength = 0x2U, /*!< DCDC_CORE regulator Drive Strength set to Normal. */ From 6a92b8efa442d0bfffa5bb43419d35d12c753910 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 4 May 2025 15:10:17 +0200 Subject: [PATCH 163/382] dcd/ci_hs: add vbus charge option. Signed-off-by: HiFiPhile --- src/portable/chipidea/ci_hs/dcd_ci_hs.c | 4 ++++ src/tusb_option.h | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/src/portable/chipidea/ci_hs/dcd_ci_hs.c b/src/portable/chipidea/ci_hs/dcd_ci_hs.c index a716dc24c..244f5a2d4 100644 --- a/src/portable/chipidea/ci_hs/dcd_ci_hs.c +++ b/src/portable/chipidea/ci_hs/dcd_ci_hs.c @@ -239,7 +239,11 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { usbmode |= USBMODE_CM_DEVICE; dcd_reg->USBMODE = usbmode; +#ifdef CFG_TUD_CI_HS_VBUS_CHARGE + dcd_reg->OTGSC = OTGSC_VBUS_CHARGE | OTGSC_OTG_TERMINATION; +#else dcd_reg->OTGSC = OTGSC_VBUS_DISCHARGE | OTGSC_OTG_TERMINATION; +#endif #if !TUD_OPT_HIGH_SPEED dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED; diff --git a/src/tusb_option.h b/src/tusb_option.h index 98f1a91b5..679b80420 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -267,6 +267,15 @@ #define CFG_TUD_DWC2_DMA_ENABLE CFG_TUD_DWC2_DMA_ENABLE_DEFAULT #endif +// Enable CI_HS VBUS Charge +#ifndef CFG_TUD_CI_HS_VBUS_CHARGE + #ifndef CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT + #define CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT 0 + #endif + + #define CFG_TUD_CI_HS_VBUS_CHARGE CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT +#endif + // Enable DWC2 Slave mode for host #ifndef CFG_TUH_DWC2_SLAVE_ENABLE #ifndef CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT From bc37ed6e3e9158a811ed07479638d3db8437344e Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 May 2025 15:23:23 +0700 Subject: [PATCH 164/382] usbh: force removed device in the same bus info, before setting address. usbh: move code around hub: queue status endpoint for detach/remove event --- src/host/hub.c | 3 +- src/host/usbh.c | 233 +++++++++++++++++++++++------------------------- 2 files changed, 115 insertions(+), 121 deletions(-) diff --git a/src/host/hub.c b/src/host/hub.c index c87289a14..0ed0e0c42 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -459,7 +459,8 @@ static void process_new_status(tuh_xfer_t* xfer) { } }; hcd_event_handler(&event, false); - processed = true; // usbh queue status after handled this in (de)enumeration + // skip status for attach event, usbh will do it after handled this enumeration + processed = (event.event_id == HCD_EVENT_DEVICE_ATTACH); break; } diff --git a/src/host/usbh.c b/src/host/usbh.c index fbb61e10e..92c254a9e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -34,7 +34,7 @@ #include "hub.h" //--------------------------------------------------------------------+ -// USBH Configuration +// Configuration //--------------------------------------------------------------------+ #ifndef CFG_TUH_TASK_QUEUE_SZ #define CFG_TUH_TASK_QUEUE_SZ 16 @@ -89,7 +89,7 @@ TU_ATTR_WEAK bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_si } //--------------------------------------------------------------------+ -// USBH-HCD common data structure +// Data Structure //--------------------------------------------------------------------+ typedef struct { tuh_bus_info_t bus_info; @@ -131,8 +131,60 @@ typedef struct { } usbh_device_t; +// sum of end device + hub +#define TOTAL_DEVICES (CFG_TUH_DEVICE_MAX + CFG_TUH_HUB) + +// all devices excluding zero-address +// hub address start from CFG_TUH_DEVICE_MAX+1 +// TODO: hub can has its own simpler struct to save memory +static usbh_device_t _usbh_devices[TOTAL_DEVICES]; + +// Mutex for claiming endpoint +#if OSAL_MUTEX_REQUIRED +static osal_mutex_def_t _usbh_mutexdef; +static osal_mutex_t _usbh_mutex; +#else +#define _usbh_mutex NULL +#endif + +// Event queue: usbh_int_set() is used as mutex in OS NONE config +OSAL_QUEUE_DEF(usbh_int_set, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); +static osal_queue_t _usbh_q; + +// Control transfers: since most controllers do not support multiple control transfers +// on multiple devices concurrently and control transfers are not used much except for +// enumeration, we will only execute control transfers one at a time. +typedef struct { + uint8_t* buffer; + tuh_xfer_cb_t complete_cb; + uintptr_t user_data; + + volatile uint8_t stage; + uint8_t daddr; + volatile uint16_t actual_len; + uint8_t failed_count; +} usbh_ctrl_xfer_info_t; + +typedef struct { + uint8_t controller_id; // controller ID + uint8_t enumerating_daddr; // device address of the device being enumerated + uint8_t attach_debouncing_bm; // bitmask for roothub port attach debouncing + tuh_bus_info_t dev0_bus; // bus info for dev0 in enumeration + usbh_ctrl_xfer_info_t ctrl_xfer_info; // control transfer +} usbh_data_t; + +static usbh_data_t _usbh_data = { + .controller_id = TUSB_INDEX_INVALID_8, +}; + +typedef struct { + TUH_EPBUF_TYPE_DEF(tusb_control_request_t, request); + TUH_EPBUF_DEF(ctrl, CFG_TUH_ENUMERATION_BUFSIZE); +} usbh_epbuf_t; +CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf; + //--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF +// Class Driver //--------------------------------------------------------------------+ #if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL #define DRIVER_NAME(_name) _name @@ -235,82 +287,58 @@ static inline usbh_class_driver_t const *get_driver(uint8_t drv_id) { } //--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION +// Function Inline and Prototypes //--------------------------------------------------------------------+ - -// sum of end device + hub -#define TOTAL_DEVICES (CFG_TUH_DEVICE_MAX + CFG_TUH_HUB) - -// all devices excluding zero-address -// hub address start from CFG_TUH_DEVICE_MAX+1 -// TODO: hub can has its own simpler struct to save memory -static usbh_device_t _usbh_devices[TOTAL_DEVICES]; - -// Mutex for claiming endpoint -#if OSAL_MUTEX_REQUIRED - static osal_mutex_def_t _usbh_mutexdef; - static osal_mutex_t _usbh_mutex; -#else - #define _usbh_mutex NULL -#endif - -// Event queue: usbh_int_set() is used as mutex in OS NONE config -OSAL_QUEUE_DEF(usbh_int_set, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); -static osal_queue_t _usbh_q; - -// Control transfers: since most controllers do not support multiple control transfers -// on multiple devices concurrently and control transfers are not used much except for -// enumeration, we will only execute control transfers one at a time. -typedef struct { - uint8_t* buffer; - tuh_xfer_cb_t complete_cb; - uintptr_t user_data; - - volatile uint8_t stage; - uint8_t daddr; - volatile uint16_t actual_len; - uint8_t failed_count; -} usbh_ctrl_xfer_info_t; - -typedef struct { - uint8_t controller_id; // controller ID - uint8_t enumerating_daddr; // device address of the device being enumerated - uint8_t attach_debouncing_bm; // bitmask for roothub port attach debouncing - tuh_bus_info_t dev0_bus; // bus info for dev0 in enumeration - usbh_ctrl_xfer_info_t ctrl_xfer_info; // control transfer -} usbh_data_t; - -static usbh_data_t _usbh_data = { - .controller_id = TUSB_INDEX_INVALID_8, -}; - -typedef struct { - TUH_EPBUF_TYPE_DEF(tusb_control_request_t, request); - TUH_EPBUF_DEF(ctrl, CFG_TUH_ENUMERATION_BUFSIZE); -} usbh_epbuf_t; -CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf; - -//------------- Helper Function -------------// -TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) { - TU_VERIFY(dev_addr > 0 && dev_addr <= TOTAL_DEVICES, NULL); - return &_usbh_devices[dev_addr-1]; -} - static bool enum_new_device(hcd_event_t* event); static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port); static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size); static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) { + TU_VERIFY(dev_addr > 0 && dev_addr <= TOTAL_DEVICES, NULL); + return &_usbh_devices[dev_addr-1]; +} + TU_ATTR_ALWAYS_INLINE static inline bool queue_event(hcd_event_t const * event, bool in_isr) { TU_ASSERT(osal_queue_send(_usbh_q, event, in_isr)); tuh_event_hook_cb(event->rhport, event->event_id, in_isr); return true; } +TU_ATTR_ALWAYS_INLINE static inline void _control_set_xfer_stage(uint8_t stage) { + if (_usbh_data.ctrl_xfer_info.stage != stage) { + (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); + _usbh_data.ctrl_xfer_info.stage = stage; + (void) osal_mutex_unlock(_usbh_mutex); + } +} + +TU_ATTR_ALWAYS_INLINE static inline bool usbh_setup_send(uint8_t daddr, const uint8_t setup_packet[8]) { + const uint8_t rhport = usbh_get_rhport(daddr); + const bool ret = hcd_setup_send(rhport, daddr, setup_packet); + if (!ret) { + _control_set_xfer_stage(CONTROL_STAGE_IDLE); + } + return ret; +} + +TU_ATTR_ALWAYS_INLINE static inline void usbh_device_close(uint8_t rhport, uint8_t daddr) { + hcd_device_close(rhport, daddr); + + // abort any ongoing control transfer + if (daddr == _usbh_data.ctrl_xfer_info.daddr) { + _control_set_xfer_stage(CONTROL_STAGE_IDLE); + } + + // invalidate if enumerating + if (daddr == _usbh_data.enumerating_daddr) { + _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; + } +} + //--------------------------------------------------------------------+ // Device API //--------------------------------------------------------------------+ - bool tuh_mounted(uint8_t dev_addr) { usbh_device_t *dev = get_device(dev_addr); TU_VERIFY(dev); @@ -530,16 +558,16 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { break; case HCD_EVENT_DEVICE_REMOVE: - TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); - process_removed_device(event.rhport, event.connection.hub_addr, event.connection.hub_port); - - #if CFG_TUH_HUB - // TODO remove - if (event.connection.hub_addr != 0 && event.connection.hub_port != 0) { - // done with hub, waiting for next data on status pipe - (void) hub_edpt_status_xfer(event.connection.hub_addr); + TU_LOG1("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); + if (_usbh_data.enumerating_daddr == 0 && + event.rhport == _usbh_data.dev0_bus.rhport && + event.connection.hub_addr == _usbh_data.dev0_bus.hub_addr && + event.connection.hub_port == _usbh_data.dev0_bus.hub_port) { + // dev0 is unplugged while enumerating (not yet assigned an address) + usbh_device_close(_usbh_data.dev0_bus.rhport, 0); + } else { + process_removed_device(event.rhport, event.connection.hub_addr, event.connection.hub_port); } - #endif break; case HCD_EVENT_XFER_COMPLETE: { @@ -623,23 +651,6 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer) { *((xfer_result_t*) xfer->user_data) = xfer->result; } -TU_ATTR_ALWAYS_INLINE static inline void _control_set_xfer_stage(uint8_t stage) { - if (_usbh_data.ctrl_xfer_info.stage != stage) { - (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); - _usbh_data.ctrl_xfer_info.stage = stage; - (void) osal_mutex_unlock(_usbh_mutex); - } -} - -TU_ATTR_ALWAYS_INLINE static inline bool usbh_setup_send(uint8_t daddr, const uint8_t setup_packet[8]) { - const uint8_t rhport = usbh_get_rhport(daddr); - const bool ret = hcd_setup_send(rhport, daddr, setup_packet); - if (!ret) { - _control_set_xfer_stage(CONTROL_STAGE_IDLE); - } - return ret; -} - // TODO timeout_ms is not supported yet bool tuh_control_xfer (tuh_xfer_t* xfer) { TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); // EP0 with setup packet @@ -1270,21 +1281,8 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { // a device unplugged from rhport:hub_addr:hub_port static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { - // if dev0 is unplugged while enumerating (not yet assigned an address) - if (_usbh_data.enumerating_daddr == 0) { - const tuh_bus_info_t* dev0_bus = &_usbh_data.dev0_bus; - if ((rhport == dev0_bus->rhport) && (hub_addr == dev0_bus->hub_addr) && (hub_port == dev0_bus->hub_port)) { - hcd_device_close(dev0_bus->rhport, 0); - if (_usbh_data.ctrl_xfer_info.daddr == 0) { - _control_set_xfer_stage(CONTROL_STAGE_IDLE); - } - _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; - return; - } - } - - //------------- find the all devices (star-network) under port that is unplugged -------------// - uint32_t removing_hubs = 0; + // Find the all devices (star-network) under port that is unplugged + uint32_t removing_hubs_bm = 0; do { for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { usbh_device_t* dev = &_usbh_devices[dev_id]; @@ -1298,7 +1296,7 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub if (is_hub_addr(daddr)) { TU_LOG_USBH(" is a HUB device %u\r\n", daddr); - removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX); + removing_hubs_bm |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX); } else { // Invoke callback before closing driver (maybe call it later ?) if (tuh_umount_cb) { @@ -1314,30 +1312,21 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub } } - hcd_device_close(rhport, daddr); + usbh_device_close(rhport, daddr); clear_device(dev); - - // abort ongoing control xfer on this device if any - if (daddr == _usbh_data.ctrl_xfer_info.daddr) { - _control_set_xfer_stage(CONTROL_STAGE_IDLE); - } - - if (daddr == _usbh_data.enumerating_daddr) { - _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8; - } } } // if removing a hub, we need to remove all of its downstream devices #if CFG_TUH_HUB - if (removing_hubs == 0) { + if (removing_hubs_bm == 0) { break; } // find a marked hub to process for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) { - if (tu_bit_test(removing_hubs, h_id)) { - removing_hubs &= ~TU_BIT(h_id); + if (tu_bit_test(removing_hubs_bm, h_id)) { + removing_hubs_bm &= ~TU_BIT(h_id); // update hub_addr and hub_port for next loop hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX; @@ -1560,6 +1549,10 @@ static void process_enumeration(tuh_xfer_t* xfer) { } case ENUM_SET_ADDR: { + // Due to physical debouncing, some devices can cause multiple attaches (actually reset) without detach event + // Force remove currently mounted with the same bus info (rhport, hub addr, hub port) if exists + process_removed_device(dev0_bus->rhport, dev0_bus->hub_addr, dev0_bus->hub_port); + const tusb_desc_device_t *desc_device = (const tusb_desc_device_t *) _usbh_epbuf.ctrl; const uint8_t new_addr = enum_get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); TU_ASSERT(new_addr != 0,); @@ -1582,7 +1575,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { new_dev->addressed = 1; _usbh_data.enumerating_daddr = new_addr; - hcd_device_close(dev0_bus->rhport, 0); // close dev0 + usbh_device_close(dev0_bus->rhport, 0); // close dev0 TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->ep0_size),); // open new control endpoint From 809af3e74ca37495d6c385acd33a488c2984a093 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 May 2025 15:44:00 +0700 Subject: [PATCH 165/382] chore(usbh): change removing_hubs to array instead of bitmask --- .idea/debugServers/rt1064.xml | 2 +- src/host/usbh.c | 37 ++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/.idea/debugServers/rt1064.xml b/.idea/debugServers/rt1064.xml index b908b59e2..4fb2fdf6a 100644 --- a/.idea/debugServers/rt1064.xml +++ b/.idea/debugServers/rt1064.xml @@ -1,5 +1,5 @@ - + diff --git a/src/host/usbh.c b/src/host/usbh.c index 92c254a9e..a3d79a105 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -299,6 +299,10 @@ TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) return &_usbh_devices[dev_addr-1]; } +TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { + return (CFG_TUH_HUB > 0) && (daddr > CFG_TUH_DEVICE_MAX); +} + TU_ATTR_ALWAYS_INLINE static inline bool queue_event(hcd_event_t const * event, bool in_isr) { TU_ASSERT(osal_queue_send(_usbh_q, event, in_isr)); tuh_event_hook_cb(event->rhport, event->event_id, in_isr); @@ -1274,15 +1278,13 @@ uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_i //--------------------------------------------------------------------+ // Detaching //--------------------------------------------------------------------+ - -TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) { - return (CFG_TUH_HUB > 0) && (daddr > CFG_TUH_DEVICE_MAX); -} - // a device unplugged from rhport:hub_addr:hub_port static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) { // Find the all devices (star-network) under port that is unplugged - uint32_t removing_hubs_bm = 0; + #if CFG_TUH_HUB + uint8_t removing_hubs[CFG_TUH_HUB] = { 0 }; + #endif + do { for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) { usbh_device_t* dev = &_usbh_devices[dev_id]; @@ -1294,10 +1296,13 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub (hub_port == 0 || dev->bus_info.hub_port == hub_port)) { TU_LOG_USBH("[%u:%u:%u] unplugged address = %u\r\n", rhport, hub_addr, hub_port, daddr); + #if CFG_TUH_HUB if (is_hub_addr(daddr)) { TU_LOG_USBH(" is a HUB device %u\r\n", daddr); - removing_hubs_bm |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX); - } else { + removing_hubs[dev_id - CFG_TUH_DEVICE_MAX] = 1; + } else + #endif + { // Invoke callback before closing driver (maybe call it later ?) if (tuh_umount_cb) { tuh_umount_cb(daddr); @@ -1317,16 +1322,16 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub } } - // if removing a hub, we need to remove all of its downstream devices - #if CFG_TUH_HUB - if (removing_hubs_bm == 0) { +#if CFG_TUH_HUB + // if a hub is removed, we need to remove all of its downstream devices + if (tu_mem_is_zero(removing_hubs, CFG_TUH_HUB)) { break; } // find a marked hub to process for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) { - if (tu_bit_test(removing_hubs_bm, h_id)) { - removing_hubs_bm &= ~TU_BIT(h_id); + if (removing_hubs[h_id]) { + removing_hubs[h_id] = 0; // update hub_addr and hub_port for next loop hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX; @@ -1334,10 +1339,10 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub break; } } - #else - (void) removing_hubs; +#else break; - #endif +#endif + } while(1); } From fb2214dea63daa8d9f44ac2a6df5835d8eabba80 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 May 2025 16:30:34 +0700 Subject: [PATCH 166/382] move hil into build workflow --- .github/workflows/build.yml | 132 ++++++++++++++++++++++++++++++++- .github/workflows/hil_test.yml | 128 -------------------------------- 2 files changed, 130 insertions(+), 130 deletions(-) delete mode 100644 .github/workflows/hil_test.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 17d578e4d..3406fb3c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,8 +8,8 @@ on: - 'examples/**' - 'lib/**' - 'hw/**' - - 'tools/get_deps.py' - 'tools/build.py' + - 'tools/get_deps.py' - '.github/actions/**' - '.github/workflows/build.yml' - '.github/workflows/build_util.yml' @@ -21,8 +21,9 @@ on: - 'examples/**' - 'lib/**' - 'hw/**' - - 'tools/get_deps.py' + - 'test/hil/**' - 'tools/build.py' + - 'tools/get_deps.py' - '.github/actions/**' - '.github/workflows/build.yml' - '.github/workflows/build_util.yml' @@ -31,7 +32,15 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +env: + HIL_JSON: test/hil/tinyusb.json + jobs: + # --------------------------------------- + # + # Build + # + # --------------------------------------- set-matrix: runs-on: ubuntu-latest outputs: @@ -151,3 +160,122 @@ jobs: run: | west build -b pca10056 -d examples/device/cdc_msc/build examples/device/cdc_msc -- -DRTOS=zephyr west build -b pca10056 -d examples/device/msc_dual_lun/build examples/device/msc_dual_lun -- -DRTOS=zephyr + + # --------------------------------------- + # + # Hardware in the loop (HIL) + # Run on PR only (hil-tinyusb), hil-hfp only run on non-forked PR + # --------------------------------------- + hil-set-matrix: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' + outputs: + json: ${{ steps.set-matrix-json.outputs.matrix }} + steps: + - name: Checkout TinyUSB + uses: actions/checkout@v4 + + - name: Generate matrix json + id: set-matrix-json + run: | + MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py ${{ env.HIL_JSON }}) + echo "matrix=$MATRIX_JSON" + echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT + + # --------------------------------------- + # Build arm-gcc + # --------------------------------------- + hil-build: + if: | + github.repository_owner == 'hathach' && + (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch') + needs: hil-set-matrix + uses: ./.github/workflows/build_util.yml + strategy: + fail-fast: false + matrix: + toolchain: + - 'arm-gcc' + - 'esp-idf' + with: + build-system: 'cmake' + toolchain: ${{ matrix.toolchain }} + build-args: ${{ toJSON(fromJSON(needs.hil-set-matrix.outputs.json)[matrix.toolchain]) }} + one-per-family: true + upload-artifacts: true + + # --------------------------------------- + # Hardware in the loop (HIL) + # self-hosted on local VM, for attached hardware checkout HIL_JSON + # --------------------------------------- + hil-tinyusb: + if: | + github.repository_owner == 'hathach' && + (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch') + needs: hil-build + runs-on: [self-hosted, X64, hathach, hardware-in-the-loop] + steps: + - name: Clean workspace + run: | + echo "Cleaning up previous run" + rm -rf "${{ github.workspace }}" + mkdir -p "${{ github.workspace }}" + + - name: Checkout TinyUSB + uses: actions/checkout@v4 + with: + sparse-checkout: test/hil + + - name: Download Artifacts + uses: actions/download-artifact@v4 + with: + path: cmake-build + merge-multiple: true + + - name: Test on actual hardware + run: | + ls cmake-build/ + python3 test/hil/hil_test.py ${{ env.HIL_JSON }} + + # --------------------------------------- + # Hardware in the loop (HIL) + # self-hosted by HFP, build with IAR toolchain, for attached hardware checkout test/hil/hfp.json + # Since IAR Token secret is not passed to forked PR, only build non-forked PR + # --------------------------------------- + hil-hfp: + if: | + github.repository_owner == 'hathach' && + github.event.pull_request.head.repo.fork == false && + (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch') + runs-on: [self-hosted, Linux, X64, hifiphile] + env: + IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} + steps: + - name: Clean workspace + run: | + echo "Cleaning up previous run" + rm -rf "${{ github.workspace }}" + mkdir -p "${{ github.workspace }}" + + - name: Toolchain version + run: | + iccarm --version + + - name: Checkout TinyUSB + uses: actions/checkout@v4 + + - name: Get build boards + run: | + MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py test/hil/hfp.json) + BUILD_ARGS=$(echo $MATRIX_JSON | jq -r '.["arm-gcc"] | join(" ")') + echo "BUILD_ARGS=$BUILD_ARGS" + echo "BUILD_ARGS=$BUILD_ARGS" >> $GITHUB_ENV + + - name: Get Dependencies + run: python3 tools/get_deps.py $BUILD_ARGS + + - name: Build + run: python3 tools/build.py --toolchain iar $BUILD_ARGS + + - name: Test on actual hardware (hardware in the loop) + run: python3 test/hil/hil_test.py hfp.json diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml deleted file mode 100644 index 0ad37ffce..000000000 --- a/.github/workflows/hil_test.yml +++ /dev/null @@ -1,128 +0,0 @@ -name: Hardware Test - -on: - workflow_dispatch: - pull_request: - branches: [ master ] - paths: - - 'src/**' - - 'examples/**' - - 'lib/**' - - 'hw/**' - - 'test/hil/**' - - 'tools/get_deps.py' - - '.github/actions/**' - - '.github/workflows/hil_test.yml' -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - HIL_JSON: test/hil/tinyusb.json - -jobs: - set-matrix: - runs-on: ubuntu-latest - outputs: - json: ${{ steps.set-matrix-json.outputs.matrix }} - steps: - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Generate matrix json - id: set-matrix-json - run: | - MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py ${{ env.HIL_JSON }}) - echo "matrix=$MATRIX_JSON" - echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT - - # --------------------------------------- - # Build arm-gcc - # --------------------------------------- - build: - if: github.repository_owner == 'hathach' - needs: set-matrix - uses: ./.github/workflows/build_util.yml - strategy: - fail-fast: false - matrix: - toolchain: - - 'arm-gcc' - - 'esp-idf' - with: - build-system: 'cmake' - toolchain: ${{ matrix.toolchain }} - build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain]) }} - one-per-family: true - upload-artifacts: true - - # --------------------------------------- - # Hardware in the loop (HIL) - # self-hosted on local VM, for attached hardware checkout HIL_JSON - # --------------------------------------- - hil-tinyusb: - if: github.repository_owner == 'hathach' - needs: build - runs-on: [self-hosted, X64, hathach, hardware-in-the-loop] - steps: - - name: Clean workspace - run: | - echo "Cleaning up previous run" - rm -rf "${{ github.workspace }}" - mkdir -p "${{ github.workspace }}" - - - name: Checkout TinyUSB - uses: actions/checkout@v4 - with: - sparse-checkout: test/hil - - - name: Download Artifacts - uses: actions/download-artifact@v4 - with: - path: cmake-build - merge-multiple: true - - - name: Test on actual hardware - run: | - ls cmake-build/ - python3 test/hil/hil_test.py ${{ env.HIL_JSON }} - - # --------------------------------------- - # Hardware in the loop (HIL) - # self-hosted by HFP, build with IAR toolchain, for attached hardware checkout test/hil/hfp.json - # Since IAR Token secret is not passed to forked PR, only build non-forked PR - # --------------------------------------- - hil-hfp: - if: github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false - runs-on: [self-hosted, Linux, X64, hifiphile] - env: - IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} - steps: - - name: Clean workspace - run: | - echo "Cleaning up previous run" - rm -rf "${{ github.workspace }}" - mkdir -p "${{ github.workspace }}" - - - name: Toolchain version - run: | - iccarm --version - - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Get build boards - run: | - MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py test/hil/hfp.json) - BUILD_ARGS=$(echo $MATRIX_JSON | jq -r '.["arm-gcc"] | join(" ")') - echo "BUILD_ARGS=$BUILD_ARGS" - echo "BUILD_ARGS=$BUILD_ARGS" >> $GITHUB_ENV - - - name: Get Dependencies - run: python3 tools/get_deps.py $BUILD_ARGS - - - name: Build - run: python3 tools/build.py --toolchain iar $BUILD_ARGS - - - name: Test on actual hardware (hardware in the loop) - run: python3 test/hil/hil_test.py hfp.json From a05fc504615edb6db2519baf97382902a9e0a60c Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 6 May 2025 18:01:30 +0700 Subject: [PATCH 167/382] clean up ci --- .github/workflows/build.yml | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3406fb3c2..28447cc80 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,6 +45,7 @@ jobs: runs-on: ubuntu-latest outputs: json: ${{ steps.set-matrix-json.outputs.matrix }} + hil_json: ${{ steps.set-matrix-json.outputs.hil_matrix }} steps: - name: Checkout TinyUSB uses: actions/checkout@v4 @@ -52,9 +53,14 @@ jobs: - name: Generate matrix json id: set-matrix-json run: | + # build matrix MATRIX_JSON=$(python .github/workflows/ci_set_matrix.py) echo "matrix=$MATRIX_JSON" echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT + # hil matrix + HIL_MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py ${{ env.HIL_JSON }}) + echo "hil_matrix=$HIL_MATRIX_JSON" + echo "hil_matrix=$HIL_MATRIX_JSON" >> $GITHUB_OUTPUT # --------------------------------------- # Build CMake @@ -166,21 +172,6 @@ jobs: # Hardware in the loop (HIL) # Run on PR only (hil-tinyusb), hil-hfp only run on non-forked PR # --------------------------------------- - hil-set-matrix: - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' - outputs: - json: ${{ steps.set-matrix-json.outputs.matrix }} - steps: - - name: Checkout TinyUSB - uses: actions/checkout@v4 - - - name: Generate matrix json - id: set-matrix-json - run: | - MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py ${{ env.HIL_JSON }}) - echo "matrix=$MATRIX_JSON" - echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT # --------------------------------------- # Build arm-gcc @@ -189,7 +180,7 @@ jobs: if: | github.repository_owner == 'hathach' && (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch') - needs: hil-set-matrix + needs: set-matrix uses: ./.github/workflows/build_util.yml strategy: fail-fast: false @@ -200,7 +191,7 @@ jobs: with: build-system: 'cmake' toolchain: ${{ matrix.toolchain }} - build-args: ${{ toJSON(fromJSON(needs.hil-set-matrix.outputs.json)[matrix.toolchain]) }} + build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.hil_json)[matrix.toolchain]) }} one-per-family: true upload-artifacts: true @@ -254,7 +245,7 @@ jobs: - name: Clean workspace run: | echo "Cleaning up previous run" - rm -rf "${{ github.workspace }}" + rm -rf "${{ github.workspace }}"3 mkdir -p "${{ github.workspace }}" - name: Toolchain version From 95be35b58727c28932dd0903c7d44fddd275df09 Mon Sep 17 00:00:00 2001 From: Moritz Scholjegerdes Date: Tue, 6 May 2025 16:06:10 +0200 Subject: [PATCH 168/382] add support for usbtmc vendor-spicific command messages --- src/class/usbtmc/usbtmc_device.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index abde9679f..d47da101f 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -45,7 +45,7 @@ */ //Limitations: -// "vendor-specific" commands are not handled. +// "vendor-specific" commands are handled similar to normal massages, except that the MsgID is changed to "vendor-specific". // Dealing with "termchar" must be handled by the application layer, // though additional error checking is does in this module. // talkOnly and listenOnly are NOT supported. They're not permitted @@ -171,6 +171,8 @@ tu_static uint8_t termChar; tu_static uint8_t termCharRequested = false; +tu_static uint8_t usbtmcVendorSpecificRequested = false; + #if OSAL_MUTEX_REQUIRED static OSAL_MUTEX_DEF(usbtmcLockBuffer); #endif @@ -226,7 +228,14 @@ bool tud_usbtmc_transmit_dev_msg_data( TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_epbuf.epin; tu_varclr(hdr); - hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; + if(usbtmcVendorSpecificRequested) + { + hdr->header.MsgID = USBTMC_MSGID_VENDOR_SPECIFIC_IN; + } + else + { + hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; + } hdr->header.bTag = usbtmc_state.lastBulkInTag; hdr->header.bTagInverse = (uint8_t)~(usbtmc_state.lastBulkInTag); hdr->TransferSize = len; @@ -512,6 +521,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint switch(msg->header.MsgID) { case USBTMC_MSGID_DEV_DEP_MSG_OUT: + usbtmcVendorSpecificRequested = false; if(!handle_devMsgOutStart(rhport, msg, xferred_bytes)) { usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); @@ -520,6 +530,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint break; case USBTMC_MSGID_DEV_DEP_MSG_IN: + usbtmcVendorSpecificRequested = false; TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); break; @@ -532,7 +543,19 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint break; #endif case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: + usbtmcVendorSpecificRequested = true; + if(!handle_devMsgOutStart(rhport, msg, xferred_bytes)) + { + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + return false; + } + break; + case USBTMC_MSGID_VENDOR_SPECIFIC_IN: + usbtmcVendorSpecificRequested = true; + TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); + break; + default: usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); return false; From f5944d35b093f63a9bd66a1b4a7414b7db5dce44 Mon Sep 17 00:00:00 2001 From: ZakDanger Date: Fri, 9 May 2025 18:17:07 +1000 Subject: [PATCH 169/382] vendor device open fix for descriptor parsing --- src/class/vendor/vendor_device.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 2fc0ac944..d7cef20ff 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -196,8 +196,9 @@ void vendord_reset(uint8_t rhport) { uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) { TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); - const uint8_t* p_desc = tu_desc_next(desc_itf); - const uint8_t* desc_end = (uint8_t const*)desc_itf + max_len; + const uint8_t* p_desc = (const uint8_t*)desc_itf; + const uint8_t* desc_end = p_desc + max_len; + p_desc = tu_desc_next(p_desc); // Find available interface vendord_interface_t* p_vendor = NULL; @@ -235,6 +236,11 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin p_desc = tu_desc_next(p_desc); } + // skip any other descriptors until the next interface descriptor, or end of all descriptors + while ( (TUSB_DESC_INTERFACE != tu_desc_type(p_desc)) && (p_desc < desc_end) ) { + p_desc = tu_desc_next(p_desc); + } + return (uint16_t) ((uintptr_t) p_desc - (uintptr_t) desc_itf); } From ae8c00f5d79629eddb22b9b442cd72f892b5eef6 Mon Sep 17 00:00:00 2001 From: ZakDanger Date: Fri, 9 May 2025 20:42:19 +1000 Subject: [PATCH 170/382] revert 'end fix' --- src/class/vendor/vendor_device.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index d7cef20ff..6f41a9f3b 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -196,9 +196,8 @@ void vendord_reset(uint8_t rhport) { uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) { TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); - const uint8_t* p_desc = (const uint8_t*)desc_itf; - const uint8_t* desc_end = p_desc + max_len; - p_desc = tu_desc_next(p_desc); + const uint8_t* p_desc = tu_desc_next(p_desc); + const uint8_t* desc_end = (const uint8_t*)desc_itf + max_len; // Find available interface vendord_interface_t* p_vendor = NULL; From 6b30a61bdbeeccf2b9447971c17d75946881b64f Mon Sep 17 00:00:00 2001 From: ZakDanger Date: Fri, 9 May 2025 20:44:11 +1000 Subject: [PATCH 171/382] revert 'end fix' --- src/class/vendor/vendor_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 6f41a9f3b..8d6e980a2 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -196,7 +196,7 @@ void vendord_reset(uint8_t rhport) { uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) { TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); - const uint8_t* p_desc = tu_desc_next(p_desc); + const uint8_t* p_desc = tu_desc_next(desc_itf); const uint8_t* desc_end = (const uint8_t*)desc_itf + max_len; // Find available interface From a2117d5d0fb0eea1f76fe7db25642df7a9c83324 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 9 May 2025 16:43:19 +0200 Subject: [PATCH 172/382] simplify vendord_open parsing loop Signed-off-by: HiFiPhile --- src/class/vendor/vendor_device.c | 37 +++++++++++--------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 8d6e980a2..0f0b0cbb2 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -210,33 +210,20 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin TU_VERIFY(p_vendor, 0); p_vendor->itf_num = desc_itf->bInterfaceNumber; - uint8_t found_ep = 0; - while (found_ep < desc_itf->bNumEndpoints) { - // skip non-endpoint descriptors - while ( (TUSB_DESC_ENDPOINT != tu_desc_type(p_desc)) && (p_desc < desc_end) ) { - p_desc = tu_desc_next(p_desc); - } - if (p_desc >= desc_end) { - break; + while (TUSB_DESC_INTERFACE != tu_desc_type(p_desc) && (desc_end - p_desc > 0)) { + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { + const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc; + TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); + + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { + tu_edpt_stream_open(&p_vendor->tx.stream, desc_ep); + tud_vendor_n_write_flush((uint8_t)(p_vendor - _vendord_itf)); + } else { + tu_edpt_stream_open(&p_vendor->rx.stream, desc_ep); + TU_ASSERT(tu_edpt_stream_read_xfer(rhport, &p_vendor->rx.stream) > 0, 0); // prepare for incoming data + } } - const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc; - TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); - found_ep++; - - if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { - tu_edpt_stream_open(&p_vendor->tx.stream, desc_ep); - tud_vendor_n_write_flush((uint8_t)(p_vendor - _vendord_itf)); - } else { - tu_edpt_stream_open(&p_vendor->rx.stream, desc_ep); - TU_ASSERT(tu_edpt_stream_read_xfer(rhport, &p_vendor->rx.stream) > 0, 0); // prepare for incoming data - } - - p_desc = tu_desc_next(p_desc); - } - - // skip any other descriptors until the next interface descriptor, or end of all descriptors - while ( (TUSB_DESC_INTERFACE != tu_desc_type(p_desc)) && (p_desc < desc_end) ) { p_desc = tu_desc_next(p_desc); } From 228b2dec1c29de2db531cc4eff98444b4221ca46 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 12 May 2025 15:40:58 +0700 Subject: [PATCH 173/382] bump ci to gcc 14 --- .github/actions/setup_toolchain/action.yml | 2 +- .github/actions/setup_toolchain/toolchain.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml index 850a3a06f..6fd5c9d4e 100644 --- a/.github/actions/setup_toolchain/action.yml +++ b/.github/actions/setup_toolchain/action.yml @@ -17,7 +17,7 @@ runs: if: inputs.toolchain == 'arm-gcc' uses: carlosperate/arm-none-eabi-gcc-action@v1 with: - release: '13.2.Rel1' + release: '14.2.Rel1' - name: Pull ESP-IDF docker if: inputs.toolchain == 'esp-idf' diff --git a/.github/actions/setup_toolchain/toolchain.json b/.github/actions/setup_toolchain/toolchain.json index 4e65f1cbe..ea07ca344 100644 --- a/.github/actions/setup_toolchain/toolchain.json +++ b/.github/actions/setup_toolchain/toolchain.json @@ -1,7 +1,7 @@ { "aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz", "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz", - "arm-gcc": "https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v13.2.1-1.1/xpack-arm-none-eabi-gcc-13.2.1-1.1-linux-x64.tar.gz", + "arm-gcc": "https://github.com/xpack-dev-tools/gcc-xpack/releases/download/v14.2.0-1/xpack-gcc-14.2.0-1-linux-x64.tar.gz", "msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2", "riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz", "rx-gcc": "https://github.com/hathach/rx_device/releases/download/0.0.1/gcc-8.3.0.202411-GNURX-ELF.run", From baf67539fc2d328a6274c35c18c90da27c37bc60 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 May 2025 10:28:42 +0700 Subject: [PATCH 174/382] fix warnings, minor clean up --- .../actions/setup_toolchain/toolchain.json | 2 +- examples/host/cdc_msc_hid/src/hid_app.c | 100 ++++++------------ src/class/cdc/cdc_host.c | 2 +- src/class/hid/hid_host.c | 6 +- src/host/hub.c | 1 - src/host/usbh.c | 5 +- 6 files changed, 41 insertions(+), 75 deletions(-) diff --git a/.github/actions/setup_toolchain/toolchain.json b/.github/actions/setup_toolchain/toolchain.json index ea07ca344..f7123ef11 100644 --- a/.github/actions/setup_toolchain/toolchain.json +++ b/.github/actions/setup_toolchain/toolchain.json @@ -1,7 +1,7 @@ { "aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz", "arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz", - "arm-gcc": "https://github.com/xpack-dev-tools/gcc-xpack/releases/download/v14.2.0-1/xpack-gcc-14.2.0-1-linux-x64.tar.gz", + "arm-gcc": "https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v14.2.1-1.1/xpack-arm-none-eabi-gcc-14.2.1-1.1-linux-x64.tar.gz", "msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2", "riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz", "rx-gcc": "https://github.com/hathach/rx_device/releases/download/0.0.1/gcc-8.3.0.202411-GNURX-ELF.run", diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index a751c9c80..6f01d6f45 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -29,14 +29,9 @@ //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM DECLARATION //--------------------------------------------------------------------+ +#define MAX_REPORT 4 -// If your host terminal support ansi escape code such as TeraTerm -// it can be use to simulate mouse cursor movement within terminal -#define USE_ANSI_ESCAPE 0 - -#define MAX_REPORT 4 - -static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; +static uint8_t const keycode2ascii[128][2] = {HID_KEYCODE_TO_ASCII}; // Each HID instance can has multiple reports static struct { @@ -45,8 +40,8 @@ static struct { } hid_info[CFG_TUH_HID]; static void process_kbd_report(hid_keyboard_report_t const *report); -static void process_mouse_report(hid_mouse_report_t const * report); -static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); +static void process_mouse_report(hid_mouse_report_t const *report); +static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len); void hid_app_task(void) { // nothing to do @@ -70,7 +65,7 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_re printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]); - // By default host stack will use activate boot protocol on supported interface. + // By default, host stack will use boot protocol on supported interface. // Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser) if (itf_protocol == HID_ITF_PROTOCOL_NONE) { hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len); @@ -121,7 +116,7 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons //--------------------------------------------------------------------+ // look up new key in previous keys -static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8_t keycode) { +static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) { for (uint8_t i = 0; i < 6; i++) { if (report->keycode[i] == keycode) { return true; @@ -130,28 +125,25 @@ static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8 return false; } -static void process_kbd_report(hid_keyboard_report_t const *report) -{ - static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released +static void process_kbd_report(hid_keyboard_report_t const *report) { + static hid_keyboard_report_t prev_report = {0, 0, {0}};// previous report to check key released //------------- example code ignore control (non-printable) key affects -------------// - for(uint8_t i=0; i<6; i++) - { - if ( report->keycode[i] ) - { - if ( find_key_in_report(&prev_report, report->keycode[i]) ) - { + for (uint8_t i = 0; i < 6; i++) { + if (report->keycode[i]) { + if (find_key_in_report(&prev_report, report->keycode[i])) { // exist in previous report means the current key is holding - }else - { + } else { // not existed in previous report means the current key is pressed bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT); uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0]; putchar(ch); - if ( ch == '\r' ) putchar('\n'); // added new line for enter key + if (ch == '\r') { + putchar('\n'); + } - #ifndef __ICCARM__ // TODO IAR doesn't support stream control ? - fflush(stdout); // flush right away, else nanolib will wait for newline + #ifndef __ICCARM__ // TODO IAR doesn't support stream control ? + fflush(stdout);// flush right away, else nanolib will wait for newline #endif } } @@ -166,55 +158,22 @@ static void process_kbd_report(hid_keyboard_report_t const *report) //--------------------------------------------------------------------+ static void cursor_movement(int8_t x, int8_t y, int8_t wheel) { -#if USE_ANSI_ESCAPE - // Move X using ansi escape - if ( x < 0) - { - printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left - }else if ( x > 0) - { - printf(ANSI_CURSOR_FORWARD(%d), x); // move right - } - - // Move Y using ansi escape - if ( y < 0) - { - printf(ANSI_CURSOR_UP(%d), (-y)); // move up - }else if ( y > 0) - { - printf(ANSI_CURSOR_DOWN(%d), y); // move down - } - - // Scroll using ansi escape - if (wheel < 0) - { - printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up - }else if (wheel > 0) - { - printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down - } - - printf("\r\n"); -#else printf("(%d %d %d)\r\n", x, y, wheel); -#endif } -static void process_mouse_report(hid_mouse_report_t const * report) -{ - static hid_mouse_report_t prev_report = { 0 }; +static void process_mouse_report(hid_mouse_report_t const *report) { + static hid_mouse_report_t prev_report = {0}; - //------------- button state -------------// + // button state uint8_t button_changed_mask = report->buttons ^ prev_report.buttons; - if ( button_changed_mask & report->buttons) - { + if (button_changed_mask & report->buttons) { printf(" %c%c%c ", - report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', - report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', - report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); + report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-', + report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-', + report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-'); } - //------------- cursor movement -------------// + // cursor movement cursor_movement(report->x, report->y, report->wheel); } @@ -263,18 +222,23 @@ static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t c if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) { switch (rpt_info->usage) { case HID_USAGE_DESKTOP_KEYBOARD: - TU_LOG1("HID receive keyboard report\r\n"); + TU_LOG2("HID receive keyboard report\r\n"); // Assume keyboard follow boot report layout process_kbd_report((hid_keyboard_report_t const *) report); break; case HID_USAGE_DESKTOP_MOUSE: - TU_LOG1("HID receive mouse report\r\n"); + TU_LOG2("HID receive mouse report\r\n"); // Assume mouse follow boot report layout process_mouse_report((hid_mouse_report_t const *) report); break; default: + printf("report[%u] ", rpt_info->report_id); + for (uint8_t i = 0; i < len; i++) { + printf("%02X ", report[i]); + } + printf("\r\n"); break; } } diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 4058857c5..bf245db3f 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -672,7 +672,7 @@ void cdch_close(uint8_t daddr) { bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) { // TODO handle stall response, retry failed transfer ... - TU_ASSERT(event == XFER_RESULT_SUCCESS); + TU_VERIFY(event == XFER_RESULT_SUCCESS); uint8_t const idx = get_idx_by_ep_addr(daddr, ep_addr); cdch_interface_t * p_cdc = get_itf(idx); diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index a3cc7d6d7..57e437196 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -444,7 +444,7 @@ bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t hidh_epbuf_t* epbuf = get_hid_epbuf(idx); if (dir == TUSB_DIR_IN) { - TU_LOG_DRV(" Get Report callback (%u, %u)\r\n", daddr, idx); + TU_LOG_DRV(" [idx=%u] Get Report callback\r\n", idx); TU_LOG3_MEM(epbuf->epin, xferred_bytes, 2); tuh_hid_report_received_cb(daddr, idx, epbuf->epin, (uint16_t) xferred_bytes); } else { @@ -461,7 +461,9 @@ void hidh_close(uint8_t daddr) { hidh_interface_t* p_hid = &_hidh_itf[i]; if (p_hid->daddr == daddr) { TU_LOG_DRV(" HIDh close addr = %u index = %u\r\n", daddr, i); - if (tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i); + if (tuh_hid_umount_cb) { + tuh_hid_umount_cb(daddr, i); + } tu_memclr(p_hid, sizeof(hidh_interface_t)); } } diff --git a/src/host/hub.c b/src/host/hub.c index 0ed0e0c42..0b172a596 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -201,7 +201,6 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, bool hub_port_get_status_local(uint8_t hub_addr, uint8_t hub_port, hub_port_status_response_t* resp) { (void) hub_port; - TU_VERIFY(hub_addr > CFG_TUH_DEVICE_MAX); hub_interface_t* p_hub = get_hub_itf(hub_addr); *resp = p_hub->port_status; return true; diff --git a/src/host/usbh.c b/src/host/usbh.c index a3d79a105..8ab1402dc 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -579,7 +579,8 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const ep_dir = (uint8_t) tu_edpt_dir(ep_addr); - TU_LOG_USBH("on EP %02X with %u bytes: %s\r\n", ep_addr, (unsigned int) event.xfer_complete.len, tu_str_xfer_result[event.xfer_complete.result]); + TU_LOG_USBH("[:%u] on EP %02X with %u bytes: %s\r\n", + event.dev_addr, ep_addr, (unsigned int) event.xfer_complete.len, tu_str_xfer_result[event.xfer_complete.result]); if (event.dev_addr == 0) { // device 0 only has control endpoint @@ -618,7 +619,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { uint8_t drv_id = dev->ep2drv[epnum][ep_dir]; usbh_class_driver_t const* driver = get_driver(drv_id); if (driver) { - TU_LOG_USBH("%s xfer callback\r\n", driver->name); + TU_LOG_USBH(" %s xfer callback\r\n", driver->name); driver->xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len); } else { From ed087b9ed83814e81d303c956de1541e9a82bb47 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 May 2025 16:13:50 +0700 Subject: [PATCH 175/382] pump up pico-pio-usb and cmsis_device_wb --- tools/get_deps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/get_deps.py b/tools/get_deps.py index d89c1b2b1..1f46a8e05 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -59,7 +59,7 @@ deps_optional = { '144f1eb7ea8c06512e12f12b27383601c0272410', 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'], 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/hathach/Pico-PIO-USB.git', - '810653f66adadba3e0e4b4b56d5167ac4f7fdbf7', + 'd15f0c62ac22348a8708e1626525fdba9466e1ee', 'rp2040'], 'hw/mcu/renesas/fsp': ['https://github.com/renesas/fsp.git', 'edcc97d684b6f716728a60d7a6fea049d9870bd6', @@ -122,7 +122,7 @@ deps_optional = { '5ad9797c54ec3e55eff770fc9b3cd4a1aefc1309', 'stm32u5'], 'hw/mcu/st/cmsis_device_wb': ['https://github.com/STMicroelectronics/cmsis_device_wb.git', - '9c5d1920dd9fabbe2548e10561d63db829bb744f', + 'd6a7fa2e7de084f5e5e47f2ab88b022fe9b50e5a', 'stm32wb'], 'hw/mcu/st/stm32-mfxstm32l152': ['https://github.com/STMicroelectronics/stm32-mfxstm32l152.git', '7f4389efee9c6a655b55e5df3fceef5586b35f9b', From fe4446090e5ab872faa973cae55839cf6929bf7e Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 13 May 2025 16:27:26 +0700 Subject: [PATCH 176/382] fix dual example for rp2350 conflict printf and cdc_printf --- .../dual/host_hid_to_device_cdc/src/main.c | 8 +++- .../dual/host_info_to_device_cdc/src/main.c | 44 ++++++++++--------- src/host/usbh.c | 6 +-- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/examples/dual/host_hid_to_device_cdc/src/main.c b/examples/dual/host_hid_to_device_cdc/src/main.c index 633f7a6ac..6f30ca381 100644 --- a/examples/dual/host_hid_to_device_cdc/src/main.c +++ b/examples/dual/host_hid_to_device_cdc/src/main.c @@ -190,7 +190,9 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { // look up new key in previous keys static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8_t keycode) { for (uint8_t i = 0; i < 6; i++) { - if (report->keycode[i] == keycode) return true; + if (report->keycode[i] == keycode) { + return true; + } } return false; @@ -230,7 +232,9 @@ static void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const* re // TODO example skips key released } - if (flush) tud_cdc_write_flush(); + if (flush) { + tud_cdc_write_flush(); + } prev_report = *report; } diff --git a/examples/dual/host_info_to_device_cdc/src/main.c b/examples/dual/host_info_to_device_cdc/src/main.c index 7e593f234..82a48fc61 100644 --- a/examples/dual/host_info_to_device_cdc/src/main.c +++ b/examples/dual/host_info_to_device_cdc/src/main.c @@ -78,6 +78,22 @@ static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_devi void led_blinking_task(void); void cdc_task(void); +#define cdc_printf(...) \ + do { \ + char _tempbuf[256]; \ + char* _bufptr = _tempbuf; \ + uint32_t count = (uint32_t) sprintf(_tempbuf, __VA_ARGS__); \ + while (count > 0) { \ + uint32_t wr_count = tud_cdc_write(_bufptr, count); \ + count -= wr_count; \ + _bufptr += wr_count; \ + if (count > 0){ \ + tud_task(); \ + tud_cdc_write_flush(); \ + } \ + } \ + } while(0) + /*------------- MAIN -------------*/ int main(void) { board_init(); @@ -160,22 +176,6 @@ void cdc_task(void) { //--------------------------------------------------------------------+ // Host Get device information //--------------------------------------------------------------------+ -#define cdc_printf(...) \ - do { \ - char _tempbuf[256]; \ - char* _bufptr = _tempbuf; \ - uint32_t count = (uint32_t) sprintf(_tempbuf, __VA_ARGS__); \ - while (count > 0) { \ - uint32_t wr_count = tud_cdc_write(_bufptr, count); \ - count -= wr_count; \ - _bufptr += wr_count; \ - if (count > 0){ \ - tud_task();\ - tud_cdc_write_flush(); \ - } \ - } \ - } while(0) - static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_device) { // Get String descriptor using Sync API uint16_t serial[64]; @@ -232,12 +232,12 @@ void tuh_enum_descriptor_device_cb(uint8_t daddr, tusb_desc_device_t const* desc } void tuh_mount_cb(uint8_t daddr) { - printf("mounted device %u\r\n", daddr); + cdc_printf("mounted device %u\r\n", daddr); is_print[daddr] = true; } void tuh_umount_cb(uint8_t daddr) { - printf("unmounted device %u\r\n", daddr); + cdc_printf("unmounted device %u\r\n", daddr); is_print[daddr] = false; } @@ -249,7 +249,9 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return;// not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); @@ -300,7 +302,9 @@ static int _count_utf8_bytes(const uint16_t *buf, size_t len) { } static void print_utf16(uint16_t *temp_buf, size_t buf_len) { - if ((temp_buf[0] & 0xff) == 0) return; // empty + if ((temp_buf[0] & 0xff) == 0) { + return;// empty + } size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t); size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len); _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len); diff --git a/src/host/usbh.c b/src/host/usbh.c index 8ab1402dc..b7d5a05f2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -547,7 +547,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { // TODO better to have an separated queue for newly attached devices if (_usbh_data.enumerating_daddr == TUSB_INDEX_INVALID_8) { // New device attached and we are ready - TU_LOG1("[%u:] USBH Device Attach\r\n", event.rhport); + TU_LOG_USBH("[%u:] USBH Device Attach\r\n", event.rhport); _usbh_data.enumerating_daddr = 0; // enumerate new device with address 0 enum_new_device(&event); } else { @@ -562,7 +562,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { break; case HCD_EVENT_DEVICE_REMOVE: - TU_LOG1("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); + TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port); if (_usbh_data.enumerating_daddr == 0 && event.rhport == _usbh_data.dev0_bus.rhport && event.connection.hub_addr == _usbh_data.dev0_bus.hub_addr && @@ -1464,7 +1464,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { bool retry = (_usbh_data.enumerating_daddr != TUSB_INDEX_INVALID_8) && (failed_count < ATTEMPT_COUNT_MAX); if (retry) { tusb_time_delay_ms_api(ATTEMPT_DELAY_MS); // delay a bit - TU_LOG1("Enumeration attempt %u/%u\r\n", failed_count+1, ATTEMPT_COUNT_MAX); + TU_LOG_USBH("Enumeration attempt %u/%u\r\n", failed_count+1, ATTEMPT_COUNT_MAX); retry = tuh_control_xfer(xfer); } From 0ebc91ec97d27c719f14708ea97053b2d46f0eed Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 May 2025 15:28:29 +0700 Subject: [PATCH 177/382] update stm32wb linker to match new startup --- .../dual/host_info_to_device_cdc/src/main.c | 2 + .../stm32wb55nucleo/stm32wb55xx_flash_cm4.ld | 45 ++++++++++++------- hw/bsp/stm32wb/family.c | 5 +-- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/examples/dual/host_info_to_device_cdc/src/main.c b/examples/dual/host_info_to_device_cdc/src/main.c index 82a48fc61..a2a505952 100644 --- a/examples/dual/host_info_to_device_cdc/src/main.c +++ b/examples/dual/host_info_to_device_cdc/src/main.c @@ -233,11 +233,13 @@ void tuh_enum_descriptor_device_cb(uint8_t daddr, tusb_desc_device_t const* desc void tuh_mount_cb(uint8_t daddr) { cdc_printf("mounted device %u\r\n", daddr); + tud_cdc_write_flush(); is_print[daddr] = true; } void tuh_umount_cb(uint8_t daddr) { cdc_printf("unmounted device %u\r\n", daddr); + tud_cdc_write_flush(); is_print[daddr] = false; } diff --git a/hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld b/hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld index 916f11866..c16235586 100644 --- a/hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld +++ b/hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld @@ -3,21 +3,26 @@ ** ** File : stm32wb55xx_flash_cm4.ld ** -** Abstract : System Workbench Minimal System calls file +** Author : STM32CubeIDE ** -** For more information about which c-functions -** need which of these lowlevel functions -** please consult the Newlib libc-manual +** Abstract : Linker script for STM32WB55xx Device +** 1024Kbytes FLASH +** 128Kbytes RAM ** -** Environment : System Workbench for MCU +** Set heap size, stack size and stack location according +** to application requirements. ** -** Distribution: The file is distributed “as is,” without any warranty +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is without any warranty ** of any kind. ** ***************************************************************************** ** @attention ** -** Copyright (c) 2019 STMicroelectronics. +** Copyright (c) 2019-2022 STMicroelectronics. ** All rights reserved. ** ** This software is licensed under terms that can be found in the LICENSE file @@ -33,7 +38,7 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ _estack = 0x20030000; /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0x400; /* required amount of heap */ +_Min_Heap_Size = 0x400; /* required amount of heap */ _Min_Stack_Size = 0x1000; /* required amount of stack */ /* Specify the memory areas */ @@ -81,14 +86,17 @@ SECTIONS . = ALIGN(4); } >FLASH - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } >FLASH - .preinit_array : + .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)) @@ -124,7 +132,6 @@ SECTIONS _edata = .; /* define a global symbol at data end */ } >RAM1 AT> FLASH - /* Uninitialized data section */ . = ALIGN(4); .bss : @@ -152,8 +159,6 @@ SECTIONS . = ALIGN(8); } >RAM1 - - /* Remove information from the standard libraries */ /DISCARD/ : { @@ -163,7 +168,15 @@ SECTIONS } .ARM.attributes 0 : { *(.ARM.attributes) } - MAPPING_TABLE (NOLOAD) : { *(MAPPING_TABLE) } >RAM_SHARED - MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED - MB_MEM2 (NOLOAD) : { _sMB_MEM2 = . ; *(MB_MEM2) ; _eMB_MEM2 = . ; } >RAM_SHARED + MAPPING_TABLE (NOLOAD) : { *(MAPPING_TABLE) } >RAM_SHARED + MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED + + /* used by the startup to initialize .MB_MEM2 data */ + _siMB_MEM2 = LOADADDR(.MB_MEM2); + .MB_MEM2 : + { + _sMB_MEM2 = . ; + *(MB_MEM2) ; + _eMB_MEM2 = . ; + } >RAM_SHARED AT> FLASH } diff --git a/hw/bsp/stm32wb/family.c b/hw/bsp/stm32wb/family.c index ba37b7cc3..93aba02fa 100644 --- a/hw/bsp/stm32wb/family.c +++ b/hw/bsp/stm32wb/family.c @@ -184,8 +184,7 @@ void HardFault_Handler(void) { asm("bkpt 1"); } -// Required by __libc_init_array in startup code if we are compiling using -// -nostdlib/-nostartfiles. +// Required by __libc_init_array in startup code if we are compiling using -nostdlib/-nostartfiles. +void _init(void); void _init(void) { - } From 38e5a67461cf7c819e845a110ef67184c2becbe4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 15 May 2025 10:27:00 +0700 Subject: [PATCH 178/382] bump up pio-usb and codeql version --- .github/workflows/codeql.yml | 6 +++--- tools/get_deps.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index be4c2dd87..a22c65c79 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -66,7 +66,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -93,7 +93,7 @@ jobs: ./.github/workflows/codeql-buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" upload: false @@ -129,7 +129,7 @@ jobs: sarif_file: ${{ steps.step1.outputs.sarif-output }} category: "/language:${{matrix.language}}" - - name: Archive CodeQL results + - name: Upload CodeQL results as an artifact uses: actions/upload-artifact@v4 with: name: codeql-results diff --git a/tools/get_deps.py b/tools/get_deps.py index 1f46a8e05..df8dbb6e1 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -59,7 +59,7 @@ deps_optional = { '144f1eb7ea8c06512e12f12b27383601c0272410', 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'], 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/hathach/Pico-PIO-USB.git', - 'd15f0c62ac22348a8708e1626525fdba9466e1ee', + '032a469e79f6a4ba40760d7868e6db26e15002d7', 'rp2040'], 'hw/mcu/renesas/fsp': ['https://github.com/renesas/fsp.git', 'edcc97d684b6f716728a60d7a6fea049d9870bd6', From 67389f37f2a9dabc33b9f180d49c827e9616572c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 May 2025 16:39:53 +0700 Subject: [PATCH 179/382] follow up to pr3118, interface also end with IAD. Add more checks --- src/class/vendor/vendor_device.c | 22 +++++++++++++++------- src/common/tusb_types.h | 6 ++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 0f0b0cbb2..7f1fd8c41 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -196,8 +196,8 @@ void vendord_reset(uint8_t rhport) { uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) { TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); - const uint8_t* p_desc = tu_desc_next(desc_itf); const uint8_t* desc_end = (const uint8_t*)desc_itf + max_len; + const uint8_t* p_desc = tu_desc_next(desc_itf); // Find available interface vendord_interface_t* p_vendor = NULL; @@ -210,17 +210,25 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin TU_VERIFY(p_vendor, 0); p_vendor->itf_num = desc_itf->bInterfaceNumber; - while (TUSB_DESC_INTERFACE != tu_desc_type(p_desc) && (desc_end - p_desc > 0)) { - if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { + while (tu_desc_is_valid(p_desc, desc_end)) { + const uint8_t desc_type = tu_desc_type(p_desc); + if (desc_type == TUSB_DESC_INTERFACE || desc_type == TUSB_DESC_INTERFACE_ASSOCIATION) { + break; // end of this interface + } else if (desc_type == TUSB_DESC_ENDPOINT) { const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc; TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); + // open endpoint stream, skip if already opened if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { - tu_edpt_stream_open(&p_vendor->tx.stream, desc_ep); - tud_vendor_n_write_flush((uint8_t)(p_vendor - _vendord_itf)); + if (p_vendor->tx.stream.ep_addr == 0) { + tu_edpt_stream_open(&p_vendor->tx.stream, desc_ep); + tud_vendor_n_write_flush((uint8_t)(p_vendor - _vendord_itf)); + } } else { - tu_edpt_stream_open(&p_vendor->rx.stream, desc_ep); - TU_ASSERT(tu_edpt_stream_read_xfer(rhport, &p_vendor->rx.stream) > 0, 0); // prepare for incoming data + if (p_vendor->rx.stream.ep_addr == 0) { + tu_edpt_stream_open(&p_vendor->rx.stream, desc_ep); + TU_ASSERT(tu_edpt_stream_read_xfer(rhport, &p_vendor->rx.stream) > 0, 0); // prepare for incoming data + } } } diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index e000a4bd3..fd7f01b67 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -586,6 +586,12 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE]; } +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_is_valid(void const* desc, uint8_t const* desc_end) { + const uint8_t* desc8 = (uint8_t const*) desc; + return (desc8 < desc_end) && (tu_desc_next(desc) <= desc_end); +} + + // find descriptor that match byte1 (type) uint8_t const * tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1); From 4f4ba3b16d9bcb98a1cb51cb6030f0be4dfd7513 Mon Sep 17 00:00:00 2001 From: Niklas Hauser Date: Sat, 17 May 2025 17:35:45 +0200 Subject: [PATCH 180/382] [stm32] Wait until the PHYC PLL is stable --- src/portable/synopsys/dwc2/dwc2_stm32.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index c11c1eb05..0bbad55f5 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -222,6 +222,10 @@ static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { // Enable PLL internal PHY USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN; + + // Wait ~2ms until the PLL is ready (there's no RDY bit to query) + uint32_t count = (SystemCoreClock / 1000) * 2; + while (count--) __NOP(); #else #endif From c8baba10f9a7a6150348618aec74719522887c93 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Wed, 9 Apr 2025 10:52:44 +0200 Subject: [PATCH 181/382] fix(dcd): Fixed race condition on device disconnect TinyUSB does not provide any locking means to protect the DCD variables. This can lead to race conditions when the user is trying to submit a transfer while the device is being disconnected. This can cause the device to be in an inconsistent state, leading to a crash or undefined behavior. This commit adds a spin-lock to protect the DCD variables during device disconnect. Closes https://github.com/espressif/esp-idf/issues/9691 Also reported in https://github.com/espressif/esp-usb/pull/131 --- src/portable/synopsys/dwc2/dcd_dwc2.c | 24 +++++++++++++++++++++ src/portable/synopsys/dwc2/dwc2_critical.h | 25 ++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/portable/synopsys/dwc2/dwc2_critical.h diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 52d675611..23273cb78 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -40,6 +40,7 @@ #include "device/dcd.h" #include "dwc2_common.h" +#include "dwc2_critical.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM @@ -52,6 +53,9 @@ typedef struct { uint8_t interval; } xfer_ctl_t; +/* +This variable is modified from ISR context, so it must be protected by critical section +*/ static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) @@ -321,6 +325,9 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } +// Since this function returns void, it is not possible to return a boolean success message +// We must make sure that this function is not called when the EP is disabled +// Must be called from critical section static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uint8_t dir) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, dir); @@ -531,6 +538,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; + DCD_ENTER_CRITICAL(); _dcd_data.allocated_epin_count = 0; // Disable non-control interrupt @@ -550,6 +558,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_rx(dwc2); dfifo_device_init(rhport); // re-init dfifo + DCD_EXIT_CRITICAL(); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { @@ -568,7 +577,12 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + DCD_ENTER_CRITICAL(); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + if (xfer->max_size == 0) { + DCD_EXIT_CRITICAL(); + return false; // Endpoint is closed + } xfer->buffer = buffer; xfer->ff = NULL; xfer->total_len = total_bytes; @@ -580,6 +594,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir); + DCD_EXIT_CRITICAL(); return true; } @@ -595,7 +610,12 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + DCD_ENTER_CRITICAL(); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + if (xfer->max_size == 0) { + DCD_EXIT_CRITICAL(); + return false; // Endpoint is closed + } xfer->buffer = NULL; xfer->ff = ff; xfer->total_len = total_bytes; @@ -603,6 +623,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t // Schedule packets to be sent within interrupt // TODO xfer fifo may only available for slave mode edpt_schedule_packets(rhport, epnum, dir); + DCD_EXIT_CRITICAL(); return true; } @@ -631,6 +652,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { //-------------------------------------------------------------------- // 7.4.1 Initialization on USB Reset +// Must be called from critical section static void handle_bus_reset(uint8_t rhport) { dwc2_regs_t *dwc2 = DWC2_REG(rhport); const uint8_t ep_count = dwc2_ep_count(dwc2); @@ -989,8 +1011,10 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. + DCD_ENTER_CRITICAL(); dwc2->gintsts = GINTSTS_USBRST; handle_bus_reset(rhport); + DCD_EXIT_CRITICAL(); } if (gintsts & GINTSTS_ENUMDNE) { diff --git a/src/portable/synopsys/dwc2/dwc2_critical.h b/src/portable/synopsys/dwc2/dwc2_critical.h new file mode 100644 index 000000000..e2508c8fd --- /dev/null +++ b/src/portable/synopsys/dwc2/dwc2_critical.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef TUSB_DWC2_CRITICAL_H_ +#define TUSB_DWC2_CRITICAL_H_ + +#include "common/tusb_mcu.h" + +#if defined(TUP_USBIP_DWC2_ESP32) + #include "freertos/FreeRTOS.h" + static portMUX_TYPE dcd_lock = portMUX_INITIALIZER_UNLOCKED; + #define DCD_ENTER_CRITICAL() portENTER_CRITICAL(&dcd_lock) + #define DCD_EXIT_CRITICAL() portEXIT_CRITICAL(&dcd_lock) + +#else + // Define critical section macros for DWC2 as no-op if not defined + // This is to avoid breaking existing code that does not use critical section + #define DCD_ENTER_CRITICAL() // no-op + #define DCD_EXIT_CRITICAL() // no-op +#endif + +#endif // TUSB_DWC2_CRITICAL_H_ From 72ee742761e5ed9cad29911ff19b8808972854ee Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 May 2025 20:09:02 +0700 Subject: [PATCH 182/382] add osal_critical API() for use with dwc2 --- src/osal/osal_freertos.h | 84 +++++++++++++++++---------- src/osal/osal_none.h | 17 ++++++ src/portable/synopsys/dwc2/dcd_dwc2.c | 82 +++++++++++++++----------- 3 files changed, 116 insertions(+), 67 deletions(-) diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index a3a0f3a3f..ba998bfa1 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -42,20 +42,20 @@ extern "C" { //--------------------------------------------------------------------+ #if configSUPPORT_STATIC_ALLOCATION - typedef StaticSemaphore_t osal_semaphore_def_t; - typedef StaticSemaphore_t osal_mutex_def_t; +typedef StaticSemaphore_t osal_semaphore_def_t; +typedef StaticSemaphore_t osal_mutex_def_t; #else - // not used therefore defined to smallest possible type to save space - typedef uint8_t osal_semaphore_def_t; - typedef uint8_t osal_mutex_def_t; + +// not used therefore defined to the smallest possible type to save space +typedef uint8_t osal_semaphore_def_t; +typedef uint8_t osal_mutex_def_t; #endif typedef SemaphoreHandle_t osal_semaphore_t; typedef SemaphoreHandle_t osal_mutex_t; typedef QueueHandle_t osal_queue_t; -typedef struct -{ +typedef struct { uint16_t depth; uint16_t item_sz; void* buf; @@ -83,16 +83,14 @@ typedef struct //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ - TU_ATTR_ALWAYS_INLINE static inline uint32_t _osal_ms2tick(uint32_t msec) { - if ( msec == OSAL_TIMEOUT_WAIT_FOREVER ) return portMAX_DELAY; - if ( msec == 0 ) return 0; + if (msec == OSAL_TIMEOUT_WAIT_FOREVER) { return portMAX_DELAY; } + if (msec == 0) { return 0; } uint32_t ticks = pdMS_TO_TICKS(msec); - // configTICK_RATE_HZ is less than 1000 and 1 tick > 1 ms - // we still need to delay at least 1 tick - if ( ticks == 0 ) ticks = 1; + // If configTICK_RATE_HZ is less than 1000 and 1 tick > 1 ms, we still need to delay at least 1 tick + if (ticks == 0) { ticks = 1; } return ticks; } @@ -101,10 +99,48 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { vTaskDelay(pdMS_TO_TICKS(msec)); } +//--------------------------------------------------------------------+ +// Critical API +//--------------------------------------------------------------------+ +#if TUSB_MCU_VENDOR_ESPRESSIF +// Espressif critical take spinlock as argument +typedef portMUX_TYPE osal_critical_t; + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { + spinlock_initialize(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { + portENTER_CRITICAL(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { + portEXIT_CRITICAL(ctx); +} + +#else + +typedef uint8_t osal_critical_t; // not used + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { + (void) ctx; + portENTER_CRITICAL(); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { + (void) ctx; + portEXIT_CRITICAL(); +} + +#endif + //--------------------------------------------------------------------+ // Semaphore API //--------------------------------------------------------------------+ - TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) { #if configSUPPORT_STATIC_ALLOCATION return xSemaphoreCreateBinaryStatic(semdef); @@ -120,19 +156,12 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t } TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - if ( !in_isr ) { + if (!in_isr) { return xSemaphoreGive(sem_hdl) != 0; } else { BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7 - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - return res != 0; } } @@ -148,7 +177,6 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t c //--------------------------------------------------------------------+ // MUTEX API (priority inheritance) //--------------------------------------------------------------------+ - TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { #if configSUPPORT_STATIC_ALLOCATION return xSemaphoreCreateMutexStatic(mdef); @@ -174,7 +202,6 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd //--------------------------------------------------------------------+ // QUEUE API //--------------------------------------------------------------------+ - TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { osal_queue_t q; @@ -201,19 +228,12 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v } TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) { - if ( !in_isr ) { + if (!in_isr) { return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0; } else { BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7 (IDF v5) - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - return res != 0; } } diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 40e9bb83a..d9100cfdd 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -40,6 +40,23 @@ extern "C" { TU_ATTR_WEAK void osal_task_delay(uint32_t msec); #endif +//--------------------------------------------------------------------+ +// Critical API +//--------------------------------------------------------------------+ +typedef uint8_t osal_critical_t; // not used + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { + (void) ctx; +} + //--------------------------------------------------------------------+ // Binary Semaphore API //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 23273cb78..5dd392409 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -40,7 +40,6 @@ #include "device/dcd.h" #include "dwc2_common.h" -#include "dwc2_critical.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM @@ -53,12 +52,12 @@ typedef struct { uint8_t interval; } xfer_ctl_t; -/* -This variable is modified from ISR context, so it must be protected by critical section -*/ +// This variable is modified from ISR context, so it must be protected by critical section static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) +static osal_critical_t _dcd_critical; + typedef struct { // EP0 transfers are limited to 1 packet - larger sizes has to be split uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type @@ -394,6 +393,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); tu_memclr(&_dcd_data, sizeof(_dcd_data)); + osal_critical_init(&_dcd_critical); // Core Initialization const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE); @@ -538,7 +538,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - DCD_ENTER_CRITICAL(); + osal_critical_enter(&_dcd_critical); _dcd_data.allocated_epin_count = 0; // Disable non-control interrupt @@ -558,7 +558,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_rx(dwc2); dfifo_device_init(rhport); // re-init dfifo - DCD_EXIT_CRITICAL(); + osal_critical_exit(&_dcd_critical); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { @@ -576,27 +576,33 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpo bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - - DCD_ENTER_CRITICAL(); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + + bool ret; + + osal_critical_enter(&_dcd_critical); + if (xfer->max_size == 0) { - DCD_EXIT_CRITICAL(); - return false; // Endpoint is closed - } - xfer->buffer = buffer; - xfer->ff = NULL; - xfer->total_len = total_bytes; + ret = false; // Endpoint is closed + } else { + xfer->buffer = buffer; + xfer->ff = NULL; + xfer->total_len = total_bytes; - // EP0 can only handle one packet - if (epnum == 0) { - _dcd_data.ep0_pending[dir] = total_bytes; + // EP0 can only handle one packet + if (epnum == 0) { + _dcd_data.ep0_pending[dir] = total_bytes; + } + + // Schedule packets to be sent within interrupt + edpt_schedule_packets(rhport, epnum, dir); + + ret = true; } - // Schedule packets to be sent within interrupt - edpt_schedule_packets(rhport, epnum, dir); - DCD_EXIT_CRITICAL(); + osal_critical_exit(&_dcd_critical); - return true; + return ret; } // The number of bytes has to be given explicitly to allow more flexible control of how many @@ -609,23 +615,29 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - - DCD_ENTER_CRITICAL(); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + + bool ret; + + osal_critical_enter(&_dcd_critical); + if (xfer->max_size == 0) { - DCD_EXIT_CRITICAL(); - return false; // Endpoint is closed + ret = false; // Endpoint is closed + } else { + xfer->buffer = NULL; + xfer->ff = ff; + xfer->total_len = total_bytes; + + // Schedule packets to be sent within interrupt + // TODO xfer fifo may only available for slave mode + edpt_schedule_packets(rhport, epnum, dir); + + ret = true; } - xfer->buffer = NULL; - xfer->ff = ff; - xfer->total_len = total_bytes; - // Schedule packets to be sent within interrupt - // TODO xfer fifo may only available for slave mode - edpt_schedule_packets(rhport, epnum, dir); - DCD_EXIT_CRITICAL(); + osal_critical_exit(&_dcd_critical); - return true; + return ret; } void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { @@ -1011,10 +1023,10 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. - DCD_ENTER_CRITICAL(); + osal_critical_enter(&_dcd_critical); dwc2->gintsts = GINTSTS_USBRST; handle_bus_reset(rhport); - DCD_EXIT_CRITICAL(); + osal_critical_exit(&_dcd_critical); } if (gintsts & GINTSTS_ENUMDNE) { From 9aea7751f292f40684d4533196037c26e2239934 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 19 May 2025 18:57:39 +0700 Subject: [PATCH 183/382] dwc2 only enter critical in isr with multiple core CPUs --- src/common/tusb_mcu.h | 7 +++++++ src/portable/synopsys/dwc2/dcd_dwc2.c | 14 ++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index a0175d664..6678265b5 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -369,6 +369,10 @@ #define TUP_DCD_ENDPOINT_MAX 7 // only 5 TX FIFO for endpoint IN #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + #if CFG_TUSB_MCU == OPT_MCU_ESP32S3 + #define TUP_MCU_MULTIPLE_CORE 1 + #endif + // Disable slave if DMA is enabled #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE @@ -381,6 +385,8 @@ #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + #define TUP_MCU_MULTIPLE_CORE 1 + // Disable slave if DMA is enabled #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE @@ -410,6 +416,7 @@ #elif TU_CHECK_MCU(OPT_MCU_RP2040) #define TUP_DCD_EDPT_ISO_ALLOC #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_MCU_MULTIPLE_CORE 1 #define TU_ATTR_FAST_FUNC __attribute__((section(".time_critical.tinyusb"))) diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 5dd392409..dc00ba82b 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -539,6 +539,7 @@ void dcd_edpt_close_all(uint8_t rhport) { uint8_t const ep_count = _dwc2_controller[rhport].ep_count; osal_critical_enter(&_dcd_critical); + _dcd_data.allocated_epin_count = 0; // Disable non-control interrupt @@ -556,8 +557,8 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_tx(dwc2, 0x10); // all tx fifo dfifo_flush_rx(dwc2); - dfifo_device_init(rhport); // re-init dfifo + osal_critical_exit(&_dcd_critical); } @@ -577,7 +578,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); - bool ret; osal_critical_enter(&_dcd_critical); @@ -596,7 +596,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir); - ret = true; } @@ -616,7 +615,6 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); - bool ret; osal_critical_enter(&_dcd_critical); @@ -631,7 +629,6 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t // Schedule packets to be sent within interrupt // TODO xfer fifo may only available for slave mode edpt_schedule_packets(rhport, epnum, dir); - ret = true; } @@ -1017,16 +1014,21 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { */ void dcd_int_handler(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); - const uint32_t gintmask = dwc2->gintmsk; const uint32_t gintsts = dwc2->gintsts & gintmask; if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. + #if TUP_MCU_MULTIPLE_CORE osal_critical_enter(&_dcd_critical); + #endif + dwc2->gintsts = GINTSTS_USBRST; handle_bus_reset(rhport); + + #if TUP_MCU_MULTIPLE_CORE osal_critical_exit(&_dcd_critical); + #endif } if (gintsts & GINTSTS_ENUMDNE) { From bffe5d97cc2f4f5a9ba8b4f09d30be97ce70a3de Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 19 May 2025 20:22:29 +0700 Subject: [PATCH 184/382] limit hil-hfp iar build to 4 parallel jobs --- .github/workflows/build.yml | 2 +- tools/build.py | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 28447cc80..fe2ed61c9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -266,7 +266,7 @@ jobs: run: python3 tools/get_deps.py $BUILD_ARGS - name: Build - run: python3 tools/build.py --toolchain iar $BUILD_ARGS + run: python3 tools/build.py -j 4 --toolchain iar $BUILD_ARGS - name: Test on actual hardware (hardware in the loop) run: python3 test/hil/hil_test.py hfp.json diff --git a/tools/build.py b/tools/build.py index d28ddd929..f2f6e6228 100755 --- a/tools/build.py +++ b/tools/build.py @@ -23,6 +23,7 @@ build_separator = '-' * 95 build_status = [STATUS_OK, STATUS_FAILED, STATUS_SKIPPED] verbose = False +parallel_jobs = os.cpu_count() # ----------------------------- # Helper @@ -110,13 +111,17 @@ def cmake_board(board, toolchain, build_flags_on): f'-DTOOLCHAIN={toolchain} {build_flags}') if rcmd.returncode == 0: cmd = f"cmake --build {build_dir}" - # circleci docker return $nproc as 36 core, limit parallel according to resource class. Required for IAR, also prevent crashed/killed by docker + njobs = parallel_jobs + + # circleci docker return $nproc as 36 core, limit parallel according to resource class. + # Required for IAR, also prevent crashed/killed by docker if os.getenv('CIRCLECI'): resource_class = { 'small': 1, 'medium': 2, 'medium+': 3, 'large': 4 } for rc in resource_class: if rc in os.getenv('CIRCLE_JOB'): - cmd += f' --parallel {resource_class[rc]}' + njobs = resource_class[rc] break + cmd += f' --parallel {njobs}' rcmd = run_cmd(cmd) ret[0 if rcmd.returncode == 0 else 1] += 1 @@ -211,6 +216,7 @@ def build_family(family, toolchain, build_system, build_flags_on, one_per_family # ----------------------------- def main(): global verbose + global parallel_jobs parser = argparse.ArgumentParser() parser.add_argument('families', nargs='*', default=[], help='Families to build') @@ -219,6 +225,7 @@ def main(): parser.add_argument('-s', '--build-system', default='cmake', help='Build system to use, default is cmake') parser.add_argument('-f1', '--build-flags-on', action='append', default=[], help='Build flag to pass to build system') parser.add_argument('-1', '--one-per-family', action='store_true', default=False, help='Build only one random board inside a family') + parser.add_argument('-j', '--jobs', type=int, default=os.cpu_count(), help='Number of jobs to run in parallel') parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output') args = parser.parse_args() @@ -229,6 +236,7 @@ def main(): build_flags_on = args.build_flags_on one_per_family = args.one_per_family verbose = args.verbose + parallel_jobs = args.jobs if len(families) == 0 and len(boards) == 0: print("Please specify families or board to build") From bb1d348eb3908543f7bc80fc462d91bba62edace Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 19 May 2025 22:51:40 +0700 Subject: [PATCH 185/382] implement osal critical for none/freertos/pico-sdk --- src/device/usbd.c | 9 +++----- src/osal/osal_freertos.h | 30 +++++++++++++++++++-------- src/osal/osal_none.h | 19 ++++++++++++----- src/osal/osal_pico.h | 21 +++++++++++++++++++ src/portable/synopsys/dwc2/dcd_dwc2.c | 19 +++++++++-------- 5 files changed, 69 insertions(+), 29 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 9c381d5e0..32de8740b 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1242,13 +1242,10 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) // USBD API For Class Driver //--------------------------------------------------------------------+ -void usbd_int_set(bool enabled) -{ - if (enabled) - { +void usbd_int_set(bool enabled) { + if (enabled) { dcd_int_enable(_usbd_rhport); - }else - { + } else { dcd_int_disable(_usbd_rhport); } } diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index ba998bfa1..5d6534709 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -102,38 +102,50 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { //--------------------------------------------------------------------+ // Critical API //--------------------------------------------------------------------+ +#define OSAL_CRITIAL_DEF(_name, _int_set) \ + osal_critical_t _name + #if TUSB_MCU_VENDOR_ESPRESSIF -// Espressif critical take spinlock as argument +// Espressif critical take spinlock as argument and does not use in_isr typedef portMUX_TYPE osal_critical_t; TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { spinlock_initialize(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { + (void) in_isr; portENTER_CRITICAL(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { + (void) in_isr; portEXIT_CRITICAL(ctx); } #else -typedef uint8_t osal_critical_t; // not used +typedef UBaseType_t osal_critical_t; TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { (void) ctx; } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { - (void) ctx; - portENTER_CRITICAL(); +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { + if (in_isr) { + *ctx = taskENTER_CRITICAL_FROM_ISR(); + } else { + taskENTER_CRITICAL(); + } } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { (void) ctx; - portEXIT_CRITICAL(); + if (in_isr) { + taskEXIT_CRITICAL_FROM_ISR(*ctx); + } else { + taskEXIT_CRITICAL(); + } } #endif diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index d9100cfdd..05a121ae6 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -43,18 +43,27 @@ TU_ATTR_WEAK void osal_task_delay(uint32_t msec); //--------------------------------------------------------------------+ // Critical API //--------------------------------------------------------------------+ -typedef uint8_t osal_critical_t; // not used +typedef struct { + void (* interrupt_set)(bool); +} osal_critical_t; + +#define OSAL_CRITIAL_DEF(_name, _int_set) \ + osal_critical_t _name = { .interrupt_set = _int_set } TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { (void) ctx; } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { - (void) ctx; +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { + if (!in_isr) { + ctx->interrupt_set(false); + } } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { - (void) ctx; +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { + if (!in_isr) { + ctx->interrupt_set(true); + } } //--------------------------------------------------------------------+ diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index 315de0950..be631ed18 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -43,6 +43,27 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { sleep_ms(msec); } +//--------------------------------------------------------------------+ +// Critical API +//--------------------------------------------------------------------+ +typedef critical_section_t osal_critical_t; +#define OSAL_CRITIAL_DEF(_name, _int_set) \ + osal_critical_t _name + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { + critical_section_init(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { + (void) in_isr; + critical_section_enter_blocking(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { + (void) in_isr; + critical_section_exit(ctx); +} + //--------------------------------------------------------------------+ // Binary Semaphore API //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index dc00ba82b..4a2dad69e 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -39,6 +39,7 @@ #define DWC2_DEBUG 2 #include "device/dcd.h" +#include "device/usbd_pvt.h" #include "dwc2_common.h" //--------------------------------------------------------------------+ @@ -56,7 +57,7 @@ typedef struct { static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) -static osal_critical_t _dcd_critical; +static OSAL_CRITIAL_DEF(_dcd_critical, usbd_int_set); typedef struct { // EP0 transfers are limited to 1 packet - larger sizes has to be split @@ -538,7 +539,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - osal_critical_enter(&_dcd_critical); + osal_critical_enter(&_dcd_critical, false); _dcd_data.allocated_epin_count = 0; @@ -559,7 +560,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_rx(dwc2); dfifo_device_init(rhport); // re-init dfifo - osal_critical_exit(&_dcd_critical); + osal_critical_exit(&_dcd_critical, false); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { @@ -580,7 +581,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_critical_enter(&_dcd_critical); + osal_critical_enter(&_dcd_critical, false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -599,7 +600,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to ret = true; } - osal_critical_exit(&_dcd_critical); + osal_critical_exit(&_dcd_critical, false); return ret; } @@ -617,7 +618,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_critical_enter(&_dcd_critical); + osal_critical_enter(&_dcd_critical, false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -632,7 +633,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t ret = true; } - osal_critical_exit(&_dcd_critical); + osal_critical_exit(&_dcd_critical, false); return ret; } @@ -1020,14 +1021,14 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. #if TUP_MCU_MULTIPLE_CORE - osal_critical_enter(&_dcd_critical); + osal_critical_enter(&_dcd_critical, true); #endif dwc2->gintsts = GINTSTS_USBRST; handle_bus_reset(rhport); #if TUP_MCU_MULTIPLE_CORE - osal_critical_exit(&_dcd_critical); + osal_critical_exit(&_dcd_critical, true); #endif } From a4875fefead1a2b27f13a588dea44eaca737f553 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 20 May 2025 16:18:00 +0700 Subject: [PATCH 186/382] rename osal_critcal to osal_spinlock add spinlock implementation for most rtos --- src/osal/osal.h | 4 ++++ src/osal/osal_freertos.h | 22 +++++++++++----------- src/osal/osal_mynewt.h | 22 ++++++++++++++++++++++ src/osal/osal_none.h | 15 ++++++++------- src/osal/osal_pico.h | 14 +++++++------- src/osal/osal_rtthread.h | 22 ++++++++++++++++++++++ src/osal/osal_rtx4.h | 19 +++++++++++++++++++ src/osal/osal_zephyr.h | 25 +++++++++++++++++++++++++ src/portable/synopsys/dwc2/dcd_dwc2.c | 20 ++++++++++---------- 9 files changed, 128 insertions(+), 35 deletions(-) diff --git a/src/osal/osal.h b/src/osal/osal.h index 38d45da44..a33280425 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -75,6 +75,10 @@ typedef void (*osal_task_func_t)( void * ); // OSAL Porting API // Should be implemented as static inline function in osal_port.h header /* + void osal_spin_init(osal_spinlock_t *ctx); + void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) + void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr); + osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); bool osal_semaphore_delete(osal_semaphore_t semd_hdl); bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr); diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 5d6534709..09b6cb338 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -100,38 +100,38 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { } //--------------------------------------------------------------------+ -// Critical API +// Spinlock API //--------------------------------------------------------------------+ -#define OSAL_CRITIAL_DEF(_name, _int_set) \ - osal_critical_t _name +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name #if TUSB_MCU_VENDOR_ESPRESSIF // Espressif critical take spinlock as argument and does not use in_isr -typedef portMUX_TYPE osal_critical_t; +typedef portMUX_TYPE osal_spinlock_t; -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { spinlock_initialize(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { (void) in_isr; portENTER_CRITICAL(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { (void) in_isr; portEXIT_CRITICAL(ctx); } #else -typedef UBaseType_t osal_critical_t; +typedef UBaseType_t osal_spinlock_t; -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { (void) ctx; } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { if (in_isr) { *ctx = taskENTER_CRITICAL_FROM_ISR(); } else { @@ -139,7 +139,7 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ct } } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { (void) ctx; if (in_isr) { taskEXIT_CRITICAL_FROM_ISR(*ctx); diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index 16def0d2a..58d226b10 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -40,6 +40,28 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { os_time_delay( os_time_ms_to_ticks32(msec) ); } +//--------------------------------------------------------------------+ +// Spinlock API +//--------------------------------------------------------------------+ +typedef os_sr_t osal_spinlock_t; + +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + OS_ENTER_CRITICAL(*ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + OS_ENTER_CRITICAL(*ctx); +} + //--------------------------------------------------------------------+ // Semaphore API //--------------------------------------------------------------------+ diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 05a121ae6..2a0170ba4 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -41,26 +41,27 @@ TU_ATTR_WEAK void osal_task_delay(uint32_t msec); #endif //--------------------------------------------------------------------+ -// Critical API +// Spinlock API //--------------------------------------------------------------------+ typedef struct { void (* interrupt_set)(bool); -} osal_critical_t; +} osal_spinlock_t; -#define OSAL_CRITIAL_DEF(_name, _int_set) \ - osal_critical_t _name = { .interrupt_set = _int_set } +// For SMP, spinlock must be locked by hardware, not use interrupt +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name = { .interrupt_set = _int_set } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { (void) ctx; } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { if (!in_isr) { ctx->interrupt_set(false); } } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { if (!in_isr) { ctx->interrupt_set(true); } diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index be631ed18..ace5907d7 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -44,22 +44,22 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { } //--------------------------------------------------------------------+ -// Critical API +// Spinlock API //--------------------------------------------------------------------+ -typedef critical_section_t osal_critical_t; -#define OSAL_CRITIAL_DEF(_name, _int_set) \ - osal_critical_t _name +typedef critical_section_t osal_spinlock_t; // pico implement critical section with spinlock +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { critical_section_init(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { (void) in_isr; critical_section_enter_blocking(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { (void) in_isr; critical_section_exit(ctx); } diff --git a/src/osal/osal_rtthread.h b/src/osal/osal_rtthread.h index c27814835..97f5dc69a 100644 --- a/src/osal/osal_rtthread.h +++ b/src/osal/osal_rtthread.h @@ -42,6 +42,28 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { rt_thread_mdelay(msec); } +//--------------------------------------------------------------------+ +// Spinlock API +//--------------------------------------------------------------------+ +typedef struct rt_spinlock osal_spinlock_t; + +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { + rt_spin_lock_init(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + rt_spin_lock(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + rt_spin_unlock(ctx); +} + //--------------------------------------------------------------------+ // Semaphore API //--------------------------------------------------------------------+ diff --git a/src/osal/osal_rtx4.h b/src/osal/osal_rtx4.h index 35909e4d6..35860ddd5 100644 --- a/src/osal/osal_rtx4.h +++ b/src/osal/osal_rtx4.h @@ -56,6 +56,25 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t msec2wait(uint32_t msec) { } } +//--------------------------------------------------------------------+ +// Spinlock API, stub not implemented +//--------------------------------------------------------------------+ +typedef uint8_t osal_spinlock_t; +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { + (void) ctx; (void) in_isr; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { + (void) ctx; (void) in_isr; +} + //--------------------------------------------------------------------+ // Semaphore API //--------------------------------------------------------------------+ diff --git a/src/osal/osal_zephyr.h b/src/osal/osal_zephyr.h index 8ecb13c6d..7a43b8ec1 100644 --- a/src/osal/osal_zephyr.h +++ b/src/osal/osal_zephyr.h @@ -35,6 +35,31 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { k_msleep(msec); } +//--------------------------------------------------------------------+ +// Spinlock API +//--------------------------------------------------------------------+ +typedef struct { + struct k_spinlock lock; + k_spinlock_key_t key; +} osal_spinlock_t; + +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + ctx->key = k_spin_lock(&ctx->lock); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + k_spin_unlock(&ctx->lock, ctx->key); +} + //--------------------------------------------------------------------+ // Binary Semaphore API //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 4a2dad69e..67484c3df 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -57,7 +57,7 @@ typedef struct { static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) -static OSAL_CRITIAL_DEF(_dcd_critical, usbd_int_set); +static OSAL_SPINLOCK_DEF(_dcd_spinlock, usbd_int_set); typedef struct { // EP0 transfers are limited to 1 packet - larger sizes has to be split @@ -394,7 +394,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); tu_memclr(&_dcd_data, sizeof(_dcd_data)); - osal_critical_init(&_dcd_critical); + osal_spin_init(&_dcd_spinlock); // Core Initialization const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE); @@ -539,7 +539,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - osal_critical_enter(&_dcd_critical, false); + osal_spin_lock(&_dcd_spinlock, false); _dcd_data.allocated_epin_count = 0; @@ -560,7 +560,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_rx(dwc2); dfifo_device_init(rhport); // re-init dfifo - osal_critical_exit(&_dcd_critical, false); + osal_spin_unlock(&_dcd_spinlock, false); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { @@ -581,7 +581,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_critical_enter(&_dcd_critical, false); + osal_spin_lock(&_dcd_spinlock, false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -600,7 +600,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to ret = true; } - osal_critical_exit(&_dcd_critical, false); + osal_spin_unlock(&_dcd_spinlock, false); return ret; } @@ -618,7 +618,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_critical_enter(&_dcd_critical, false); + osal_spin_lock(&_dcd_spinlock, false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -633,7 +633,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t ret = true; } - osal_critical_exit(&_dcd_critical, false); + osal_spin_unlock(&_dcd_spinlock, false); return ret; } @@ -1021,14 +1021,14 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. #if TUP_MCU_MULTIPLE_CORE - osal_critical_enter(&_dcd_critical, true); + osal_spin_lock(&_dcd_spinlock, true); #endif dwc2->gintsts = GINTSTS_USBRST; handle_bus_reset(rhport); #if TUP_MCU_MULTIPLE_CORE - osal_critical_exit(&_dcd_critical, true); + osal_spin_unlock(&_dcd_spinlock, true); #endif } From c1d23a0a92bef016e22be3ed8194230cfab1c358 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 May 2025 11:19:07 +0700 Subject: [PATCH 187/382] osal_spin skipping lock/unlock when executed in isr --- src/osal/osal_freertos.h | 17 ++++++++++++++--- src/osal/osal_mynewt.h | 8 ++++++-- src/osal/osal_none.h | 2 +- src/osal/osal_rtthread.h | 8 ++++++-- src/osal/osal_zephyr.h | 8 ++++++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 9 ++------- src/portable/synopsys/dwc2/dwc2_esp32.h | 4 ++-- 7 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 09b6cb338..bde5ec010 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -114,12 +114,16 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } portENTER_CRITICAL(ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } portEXIT_CRITICAL(ctx); } @@ -133,6 +137,10 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { if (in_isr) { + if (!TUP_MCU_MULTIPLE_CORE) { + (void) ctx; + return; // single core MCU does not need to lock in ISR + } *ctx = taskENTER_CRITICAL_FROM_ISR(); } else { taskENTER_CRITICAL(); @@ -140,8 +148,11 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bo } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) ctx; if (in_isr) { + if (!TUP_MCU_MULTIPLE_CORE) { + (void) ctx; + return; // single core MCU does not need to lock in ISR + } taskEXIT_CRITICAL_FROM_ISR(*ctx); } else { taskEXIT_CRITICAL(); diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index 58d226b10..ee95e684f 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -53,12 +53,16 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } OS_ENTER_CRITICAL(*ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } OS_ENTER_CRITICAL(*ctx); } diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 2a0170ba4..a8eb1042b 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -47,7 +47,7 @@ typedef struct { void (* interrupt_set)(bool); } osal_spinlock_t; -// For SMP, spinlock must be locked by hardware, not use interrupt +// For SMP, spinlock must be locked by hardware, cannot just use interrupt #define OSAL_SPINLOCK_DEF(_name, _int_set) \ osal_spinlock_t _name = { .interrupt_set = _int_set } diff --git a/src/osal/osal_rtthread.h b/src/osal/osal_rtthread.h index 97f5dc69a..a778f5425 100644 --- a/src/osal/osal_rtthread.h +++ b/src/osal/osal_rtthread.h @@ -55,12 +55,16 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } rt_spin_lock(ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } rt_spin_unlock(ctx); } diff --git a/src/osal/osal_zephyr.h b/src/osal/osal_zephyr.h index 7a43b8ec1..91f225f79 100644 --- a/src/osal/osal_zephyr.h +++ b/src/osal/osal_zephyr.h @@ -51,12 +51,16 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } ctx->key = k_spin_lock(&ctx->lock); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } k_spin_unlock(&ctx->lock, ctx->key); } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 67484c3df..19eac6e15 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1020,16 +1020,11 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. - #if TUP_MCU_MULTIPLE_CORE - osal_spin_lock(&_dcd_spinlock, true); - #endif - dwc2->gintsts = GINTSTS_USBRST; - handle_bus_reset(rhport); - #if TUP_MCU_MULTIPLE_CORE + osal_spin_lock(&_dcd_spinlock, true); + handle_bus_reset(rhport); osal_spin_unlock(&_dcd_spinlock, true); - #endif } if (gintsts & GINTSTS_ENUMDNE) { diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index 3309760ff..49b8c54cb 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -55,8 +55,8 @@ static const dwc2_controller_t _dwc2_controller[] = { // On ESP32 for consistency we associate // - Port0 to OTG_FS, and Port1 to OTG_HS static const dwc2_controller_t _dwc2_controller[] = { -{ .reg_base = DWC2_FS_REG_BASE, .irqnum = ETS_USB_OTG11_CH0_INTR_SOURCE, .ep_count = 7, .ep_in_count = 5, .ep_fifo_size = 1024 }, -{ .reg_base = DWC2_HS_REG_BASE, .irqnum = ETS_USB_OTG_INTR_SOURCE, .ep_count = 16, .ep_in_count = 8, .ep_fifo_size = 4096 } + { .reg_base = DWC2_FS_REG_BASE, .irqnum = ETS_USB_OTG11_CH0_INTR_SOURCE, .ep_count = 7, .ep_in_count = 5, .ep_fifo_size = 1024 }, + { .reg_base = DWC2_HS_REG_BASE, .irqnum = ETS_USB_OTG_INTR_SOURCE, .ep_count = 16, .ep_in_count = 8, .ep_fifo_size = 4096 } }; #endif From 5551a3e430c1a330ec2a09121abc79fbb7b3c7b0 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 May 2025 11:41:06 +0700 Subject: [PATCH 188/382] add usbd_spin_lock/unlock for driver usage --- src/device/usbd.c | 22 ++++++++++++++++------ src/device/usbd_pvt.h | 2 ++ src/portable/synopsys/dwc2/dcd_dwc2.c | 19 ++++++++----------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 32de8740b..6e5fcf3b6 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -340,15 +340,16 @@ TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8 enum { RHPORT_INVALID = 0xFFu }; tu_static uint8_t _usbd_rhport = RHPORT_INVALID; -// Event queue -// usbd_int_set() is used as mutex in OS NONE config +static OSAL_SPINLOCK_DEF(_usbd_spin, usbd_int_set); + +// Event queue: usbd_int_set() is used as mutex in OS NONE config OSAL_QUEUE_DEF(usbd_int_set, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); -tu_static osal_queue_t _usbd_q; +static osal_queue_t _usbd_q; // Mutex for claiming endpoint #if OSAL_MUTEX_REQUIRED - tu_static osal_mutex_def_t _ubsd_mutexdef; - tu_static osal_mutex_t _usbd_mutex; + static osal_mutex_def_t _ubsd_mutexdef; + static osal_mutex_t _usbd_mutex; #else #define _usbd_mutex NULL #endif @@ -466,7 +467,7 @@ bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { TU_ASSERT(rh_init); TU_LOG_USBD("USBD init on controller %u, speed = %s\r\n", rhport, - rh_init->speed == TUSB_SPEED_HIGH ? "High" : "Full"); + rh_init->speed == TUSB_SPEED_HIGH ? "High" : "Full"); TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(usbd_device_t)); TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(dcd_event_t)); TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_fifo_t)); @@ -475,6 +476,8 @@ bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_varclr(&_usbd_dev); _usbd_queued_setup = 0; + osal_spin_init(&_usbd_spin); + #if OSAL_MUTEX_REQUIRED // Init device mutex _usbd_mutex = osal_mutex_create(&_ubsd_mutexdef); @@ -1250,6 +1253,13 @@ void usbd_int_set(bool enabled) { } } +void usbd_spin_lock(bool in_isr) { + osal_spin_lock(&_usbd_spin, in_isr); +} +void usbd_spin_unlock(bool in_isr) { + osal_spin_unlock(&_usbd_spin, in_isr); +} + // Parse consecutive endpoint descriptors (IN & OUT) bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in) { diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 190d6fd7f..5c6f9dbee 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -68,6 +68,8 @@ usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); void usbd_int_set(bool enabled); +void usbd_spin_lock(bool in_isr); +void usbd_spin_unlock(bool in_isr); //--------------------------------------------------------------------+ // USBD Endpoint API diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 19eac6e15..865c51894 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -57,8 +57,6 @@ typedef struct { static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) -static OSAL_SPINLOCK_DEF(_dcd_spinlock, usbd_int_set); - typedef struct { // EP0 transfers are limited to 1 packet - larger sizes has to be split uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type @@ -394,7 +392,6 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); tu_memclr(&_dcd_data, sizeof(_dcd_data)); - osal_spin_init(&_dcd_spinlock); // Core Initialization const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE); @@ -539,7 +536,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - osal_spin_lock(&_dcd_spinlock, false); + usbd_spin_lock(false); _dcd_data.allocated_epin_count = 0; @@ -560,7 +557,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_rx(dwc2); dfifo_device_init(rhport); // re-init dfifo - osal_spin_unlock(&_dcd_spinlock, false); + usbd_spin_unlock(false); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { @@ -581,7 +578,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_spin_lock(&_dcd_spinlock, false); + usbd_spin_lock(false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -600,7 +597,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to ret = true; } - osal_spin_unlock(&_dcd_spinlock, false); + usbd_spin_unlock(false); return ret; } @@ -618,7 +615,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_spin_lock(&_dcd_spinlock, false); + usbd_spin_lock(false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -633,7 +630,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t ret = true; } - osal_spin_unlock(&_dcd_spinlock, false); + usbd_spin_unlock(false); return ret; } @@ -1022,9 +1019,9 @@ void dcd_int_handler(uint8_t rhport) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; - osal_spin_lock(&_dcd_spinlock, true); + usbd_spin_lock(true); handle_bus_reset(rhport); - osal_spin_unlock(&_dcd_spinlock, true); + usbd_spin_unlock(true); } if (gintsts & GINTSTS_ENUMDNE) { From 58dfc126ac96d151bc6a9e9ee8bda564b52c350f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 May 2025 14:36:53 +0700 Subject: [PATCH 189/382] remove unused dwc2_critical.h --- src/portable/synopsys/dwc2/dwc2_critical.h | 25 ---------------------- 1 file changed, 25 deletions(-) delete mode 100644 src/portable/synopsys/dwc2/dwc2_critical.h diff --git a/src/portable/synopsys/dwc2/dwc2_critical.h b/src/portable/synopsys/dwc2/dwc2_critical.h deleted file mode 100644 index e2508c8fd..000000000 --- a/src/portable/synopsys/dwc2/dwc2_critical.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef TUSB_DWC2_CRITICAL_H_ -#define TUSB_DWC2_CRITICAL_H_ - -#include "common/tusb_mcu.h" - -#if defined(TUP_USBIP_DWC2_ESP32) - #include "freertos/FreeRTOS.h" - static portMUX_TYPE dcd_lock = portMUX_INITIALIZER_UNLOCKED; - #define DCD_ENTER_CRITICAL() portENTER_CRITICAL(&dcd_lock) - #define DCD_EXIT_CRITICAL() portEXIT_CRITICAL(&dcd_lock) - -#else - // Define critical section macros for DWC2 as no-op if not defined - // This is to avoid breaking existing code that does not use critical section - #define DCD_ENTER_CRITICAL() // no-op - #define DCD_EXIT_CRITICAL() // no-op -#endif - -#endif // TUSB_DWC2_CRITICAL_H_ From e41a63c60dbebd9579698e6444bc62cfa518e15c Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 May 2025 15:27:18 +0700 Subject: [PATCH 190/382] add usbh_spin_lock/unlock() use spinlock instead of atomic flag for hcd max3421 --- .../adafruit_feather_esp32c6/board.cmake | 3 + .../boards/adafruit_feather_esp32c6/board.h | 56 +++++++++++++++ hw/bsp/espressif/boards/family.c | 2 + src/host/usbh.c | 13 ++++ src/host/usbh_pvt.h | 3 + src/portable/analog/max3421/hcd_max3421.c | 69 ++++++++++++++----- 6 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.cmake create mode 100644 hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.h diff --git a/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.cmake b/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.cmake new file mode 100644 index 000000000..9adaefb17 --- /dev/null +++ b/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.cmake @@ -0,0 +1,3 @@ +# Apply board specific content here +set(IDF_TARGET "esp32c6") +set(MAX3421_HOST 1) diff --git a/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.h b/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.h new file mode 100644 index 000000000..18b51410d --- /dev/null +++ b/hw/bsp/espressif/boards/adafruit_feather_esp32c6/board.h @@ -0,0 +1,56 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: Adafruit Feather EPS32-C6 + url: https://www.adafruit.com/product/5933 +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define NEOPIXEL_PIN 15 + +#define BUTTON_PIN 9 +#define BUTTON_STATE_ACTIVE 0 + +// SPI for USB host shield +#define MAX3421_SPI_HOST SPI2_HOST +#define MAX3421_SCK_PIN 21 +#define MAX3421_MOSI_PIN 22 +#define MAX3421_MISO_PIN 23 +#define MAX3421_CS_PIN 8 +#define MAX3421_INTR_PIN 7 + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index cf11e2441..8f6c4bee2 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -49,7 +49,9 @@ static led_strip_handle_t led_strip; static void max3421_init(void); #endif +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4) static bool usb_init(void); +#endif //--------------------------------------------------------------------+ // Implementation diff --git a/src/host/usbh.c b/src/host/usbh.c index b7d5a05f2..f2e5c1f0e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -147,6 +147,9 @@ static osal_mutex_t _usbh_mutex; #define _usbh_mutex NULL #endif +// Spinlock for interrupt handler +static OSAL_SPINLOCK_DEF(_usbh_spin, usbh_int_set); + // Event queue: usbh_int_set() is used as mutex in OS NONE config OSAL_QUEUE_DEF(usbh_int_set, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t); static osal_queue_t _usbh_q; @@ -424,6 +427,8 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { TU_LOG_INT_USBH(sizeof(tu_fifo_t)); TU_LOG_INT_USBH(sizeof(tu_edpt_stream_t)); + osal_spin_init(&_usbh_spin); + // Event queue _usbh_q = osal_queue_create(&_usbh_qdef); TU_ASSERT(_usbh_q != NULL); @@ -895,6 +900,14 @@ void usbh_int_set(bool enabled) { } } +void usbh_spin_lock(bool in_isr) { + osal_spin_lock(&_usbh_spin, in_isr); +} + +void usbh_spin_unlock(bool in_isr) { + osal_spin_unlock(&_usbh_spin, in_isr); +} + void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr) { hcd_event_t event = { 0 }; event.event_id = USBH_EVENT_FUNC_CALL; diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index 61b012493..cb092e5f3 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -71,6 +71,9 @@ void usbh_int_set(bool enabled); void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr); +void usbh_spin_lock(bool in_isr); +void usbh_spin_unlock(bool in_isr); + //--------------------------------------------------------------------+ // USBH Endpoint API //--------------------------------------------------------------------+ diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index bb33200f2..971dbd62e 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -28,9 +28,9 @@ #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 -#include #include "host/hcd.h" #include "host/usbh.h" +#include "host/usbh_pvt.h" //--------------------------------------------------------------------+ // @@ -233,7 +233,7 @@ typedef struct { uint8_t hxfr; }sndfifo_owner; - atomic_flag busy; // busy transferring + bool busy_lock; // busy transferring #if OSAL_MUTEX_REQUIRED OSAL_MUTEX_DEF(spi_mutexdef); @@ -327,7 +327,9 @@ TU_ATTR_ALWAYS_INLINE static inline void mode_write(uint8_t rhport, uint8_t data } TU_ATTR_ALWAYS_INLINE static inline void peraddr_write(uint8_t rhport, uint8_t data, bool in_isr) { - if ( _hcd_data.peraddr == data ) return; // no need to change address + if (_hcd_data.peraddr == data) { + return; // no need to change address + } _hcd_data.peraddr = data; reg_write(rhport, PERADDR_ADDR, data, in_isr); @@ -373,7 +375,7 @@ TU_ATTR_ALWAYS_INLINE static inline void hwfifo_setup(uint8_t rhport, const uint static void hwfifo_receive(uint8_t rhport, uint8_t * buffer, uint16_t len, bool in_isr) { uint8_t hirq; - uint8_t const reg = RCVVFIFO_ADDR; + const uint8_t reg = RCVVFIFO_ADDR; max3421_spi_lock(rhport, in_isr); @@ -389,7 +391,7 @@ static void hwfifo_receive(uint8_t rhport, uint8_t * buffer, uint16_t len, bool //--------------------------------------------------------------------+ static max3421_ep_t* find_ep_not_addr0(uint8_t daddr, uint8_t ep_num, uint8_t ep_dir) { - uint8_t const is_out = 1-ep_dir; + const uint8_t is_out = 1-ep_dir; for(size_t i=1; ixferred_len = 0; ep->state = EP_STATE_ATTEMPT_1; + bool has_xfer = false; + + usbh_spin_lock(false); + if (!_hcd_data.busy_lock) { + _hcd_data.busy_lock = true; + has_xfer = true; + } + usbh_spin_unlock(false); + // carry out transfer if not busy - if (!atomic_flag_test_and_set(&_hcd_data.busy)) { + if (has_xfer) { xact_generic(rhport, ep, true, false); } @@ -781,8 +792,17 @@ bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8] ep->xferred_len = 0; ep->state = EP_STATE_ATTEMPT_1; + bool has_xfer = false; + + usbh_spin_lock(false); + if (!_hcd_data.busy_lock) { + _hcd_data.busy_lock = true; + has_xfer = true; + } + usbh_spin_unlock(false); + // carry out transfer if not busy - if (!atomic_flag_test_and_set(&_hcd_data.busy)) { + if (has_xfer) { xact_setup(rhport, ep, false); } @@ -848,8 +868,8 @@ static void handle_connect_irq(uint8_t rhport, bool in_isr) { } static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t hrsl, bool in_isr) { - uint8_t const ep_dir = 1-ep->hxfr_bm.is_out; - uint8_t const ep_addr = tu_edpt_addr(ep->hxfr_bm.ep_num, ep_dir); + const uint8_t ep_dir = 1 - ep->hxfr_bm.is_out; + const uint8_t ep_addr = tu_edpt_addr(ep->hxfr_bm.ep_num, ep_dir); // save data toggle if (ep_dir) { @@ -867,7 +887,9 @@ static void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t re xact_generic(rhport, next_ep, true, in_isr); }else { // no more pending - atomic_flag_clear(&_hcd_data.busy); + usbh_spin_lock(in_isr); + _hcd_data.busy_lock = false; + usbh_spin_unlock(in_isr); } } @@ -906,7 +928,9 @@ static void handle_xfer_done(uint8_t rhport, bool in_isr) { xact_generic(rhport, next_ep, true, in_isr); } else { // no more pending in this frame -> clear busy - atomic_flag_clear(&_hcd_data.busy); + usbh_spin_lock(in_isr); + _hcd_data.busy_lock = false; + usbh_spin_unlock(in_isr); } return; @@ -997,8 +1021,8 @@ void print_hirq(uint8_t hirq) { // Interrupt handler void hcd_int_handler(uint8_t rhport, bool in_isr) { uint8_t hirq = reg_read(rhport, HIRQ_ADDR, in_isr) & _hcd_data.hien; - if (!hirq) return; -// print_hirq(hirq); + if (!hirq) { return; } + // print_hirq(hirq); if (hirq & HIRQ_FRAME_IRQ) { _hcd_data.frame_count++; @@ -1017,8 +1041,19 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { } // start usb transfer if not busy - if (ep_retry != NULL && !atomic_flag_test_and_set(&_hcd_data.busy)) { - xact_generic(rhport, ep_retry, true, in_isr); + if (ep_retry != NULL) { + bool has_xfer = false; + + usbh_spin_lock(in_isr); + if (!_hcd_data.busy_lock) { + _hcd_data.busy_lock = true; + has_xfer = true; + } + usbh_spin_unlock(in_isr); + + if (has_xfer) { + xact_generic(rhport, ep_retry, true, in_isr); + } } } From a484b2e37291dfe5062348d3460bffc60e04e366 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 May 2025 15:59:55 +0700 Subject: [PATCH 191/382] update bug template to include commit SHA --- .github/ISSUE_TEMPLATE/bug_report.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index d00ee78bd..35576a439 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -22,10 +22,17 @@ body: validations: required: true + - type: input + attributes: + label: Commit SHA + placeholder: e.g 3a042b37da28d0ba1e5593eb1068ca5645d77b56 or version bundled by esp-idf or pico-sdk + validations: + required: true + - type: input attributes: label: Board - placeholder: e.g Feather nRF52840 Express + placeholder: e.g Adafruit Feather nRF52840 Express validations: required: true From 1a13bd8eba883aa9d1fda8f95823db8217c912f4 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 23 May 2025 13:27:27 +0200 Subject: [PATCH 192/382] Add comment about CFG_TUD_CI_HS_VBUS_CHARGE Signed-off-by: HiFiPhile --- src/tusb_option.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tusb_option.h b/src/tusb_option.h index 679b80420..6d733a429 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -267,7 +267,7 @@ #define CFG_TUD_DWC2_DMA_ENABLE CFG_TUD_DWC2_DMA_ENABLE_DEFAULT #endif -// Enable CI_HS VBUS Charge +// Enable CI_HS VBUS Charge. Set this to 1 if the USB_VBUS pin is not connected to 5V VBUS (note: 3.3V is insufficient). #ifndef CFG_TUD_CI_HS_VBUS_CHARGE #ifndef CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT #define CFG_TUD_CI_HS_VBUS_CHARGE_DEFAULT 0 From 132c55aca0aa9bb68b4ffb96ec89947e08e19b88 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 28 May 2025 08:38:26 +0700 Subject: [PATCH 193/382] add OPT_MCU_MAX32665 --- .github/workflows/codeql.yml | 2 +- src/CMakeLists.txt | 5 +---- src/tusb_option.h | 1 + tools/build.py | 4 ++-- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index a22c65c79..dfcca6315 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -124,7 +124,7 @@ jobs: output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif - name: Upload SARIF - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ steps.step1.outputs.sarif-output }} category: "/language:${{matrix.language}}" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 55c52033c..99d3059fc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,9 +1,6 @@ -# TODO more docs and example on how to use this file -# TINYUSB_TARGET_PREFIX and TINYUSB_TARGET_SUFFIX can be used to change the name of the target - cmake_minimum_required(VERSION 3.20) -# Add tinyusb to a existing target +# Add tinyusb to a existing target, DCD and HCD drivers are not included function(tinyusb_target_add TARGET) target_sources(${TARGET} PRIVATE # common diff --git a/src/tusb_option.h b/src/tusb_option.h index 6d733a429..104f669c9 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -195,6 +195,7 @@ // Analog Devices #define OPT_MCU_MAX32690 2400 ///< ADI MAX32690 +#define OPT_MCU_MAX32665 2401 ///< ADI MAX32666/5 #define OPT_MCU_MAX32666 2401 ///< ADI MAX32666/5 #define OPT_MCU_MAX32650 2402 ///< ADI MAX32650/1/2 #define OPT_MCU_MAX78002 2403 ///< ADI MAX78002 diff --git a/tools/build.py b/tools/build.py index f2f6e6228..6e73681fe 100755 --- a/tools/build.py +++ b/tools/build.py @@ -101,13 +101,13 @@ def cmake_board(board, toolchain, build_flags_on): if build_utils.skip_example(example, board): ret[2] += 1 else: - rcmd = run_cmd(f'cmake examples/{example} -B {build_dir}/{example} -G "Ninja" ' + rcmd = run_cmd(f'cmake examples/{example} -B {build_dir}/{example} -G Ninja ' f'-DBOARD={board} {build_flags}') if rcmd.returncode == 0: rcmd = run_cmd(f'cmake --build {build_dir}/{example}') ret[0 if rcmd.returncode == 0 else 1] += 1 else: - rcmd = run_cmd(f'cmake examples -B {build_dir} -G "Ninja" -DBOARD={board} -DCMAKE_BUILD_TYPE=MinSizeRel ' + rcmd = run_cmd(f'cmake examples -B {build_dir} -G Ninja -DBOARD={board} -DCMAKE_BUILD_TYPE=MinSizeRel ' f'-DTOOLCHAIN={toolchain} {build_flags}') if rcmd.returncode == 0: cmd = f"cmake --build {build_dir}" From 5de4a23abe315ecc5f9387ced910f54e29e0e69e Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Tue, 27 May 2025 15:06:05 +1000 Subject: [PATCH 194/382] Add USB NCM link state control support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds the ability to dynamically control the network link state for NCM devices. The host OS will see the network interface as connected/disconnected based on the link state. New API: - tud_network_link_state(rhport, is_up): Set link up/down state Example updates: - Added button control to toggle link state - Fixed LWIP integration to properly handle link state changes - Added printf to show correct protocol (NCM vs RNDIS/ECM) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../device/net_lwip_webserver/src/lwipopts.h | 1 + examples/device/net_lwip_webserver/src/main.c | 73 ++++++++++++++++--- .../net_lwip_webserver/src/tusb_config.h | 2 + src/class/net/ncm_device.c | 36 ++++++++- src/class/net/net_device.h | 5 ++ 5 files changed, 107 insertions(+), 10 deletions(-) diff --git a/examples/device/net_lwip_webserver/src/lwipopts.h b/examples/device/net_lwip_webserver/src/lwipopts.h index 41e8f0d67..04949cef9 100644 --- a/examples/device/net_lwip_webserver/src/lwipopts.h +++ b/examples/device/net_lwip_webserver/src/lwipopts.h @@ -58,6 +58,7 @@ #define LWIP_HTTPD_SSI_INCLUDE_TAG 0 #define LWIP_SINGLE_NETIF 1 +#define LWIP_NETIF_LINK_CALLBACK 1 #define PBUF_POOL_SIZE 4 diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 36f402332..41f02576f 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -31,6 +31,12 @@ this appears as either a RNDIS or CDC-ECM USB virtual network adapter; the OS pi RNDIS should be valid on Linux and Windows hosts, and CDC-ECM should be valid on Linux and macOS hosts The MCU appears to the host as IP address 192.168.7.1, and provides a DHCP server, DNS server, and web server. + +Link State Control: +- Press the user button to toggle the network link state (UP/DOWN) +- This simulates "ethernet cable unplugged/plugged" events +- The host OS will see the network interface as disconnected/connected accordingly +- Use this to test network error handling and recovery in host applications */ /* Some smartphones *may* work with this implementation as well, but likely have limited (broken) drivers, @@ -137,6 +143,12 @@ static err_t netif_init_cb(struct netif *netif) { return ERR_OK; } +/* notifies the USB host about the link state change. */ +static void usbnet_netif_link_callback(struct netif *netif) { + bool link_up = netif_is_link_up(netif); + tud_network_link_state(BOARD_TUD_RHPORT, link_up); +} + static void init_lwip(void) { struct netif *netif = &netif_data; @@ -147,11 +159,19 @@ static void init_lwip(void) { memcpy(netif->hwaddr, tud_network_mac_address, sizeof(tud_network_mac_address)); netif->hwaddr[5] ^= 0x01; - netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ip_input); + netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, netif_init_cb, ethernet_input); #if LWIP_IPV6 netif_create_ip6_linklocal_address(netif, 1); #endif netif_set_default(netif); + +#if LWIP_NETIF_LINK_CALLBACK + // Set the link callback to notify USB host about link state changes + netif_set_link_callback(netif, usbnet_netif_link_callback); + netif_set_link_up(netif); +#else + tud_network_link_state(BOARD_TUD_RHPORT, true); +#endif } /* handle any DNS requests from dns-server */ @@ -171,13 +191,16 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { if (size) { struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); - if (p) { - /* pbuf_alloc() has already initialized struct; all we need to do is copy the data */ - memcpy(p->payload, src, size); - - /* store away the pointer for service_traffic() to later handle */ - received_frame = p; + if (p == NULL) { + printf("ERROR: Failed to allocate pbuf of size %d\n", size); + return false; } + + /* Copy buf to pbuf */ + pbuf_take(p, src, size); + + /* store away the pointer for service_traffic() to later handle */ + received_frame = p; } return true; @@ -194,12 +217,14 @@ uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) { static void service_traffic(void) { /* handle any packet received by tud_network_recv_cb() */ if (received_frame) { + struct netif *netif = &netif_data; // Surrender ownership of our pbuf unless there was an error // Only call pbuf_free if not Ok else it will panic with "pbuf_free: p->ref > 0" // or steal it from whatever took ownership of it with undefined consequences. // See: https://savannah.nongnu.org/patch/index.php?10121 - if (ethernet_input(received_frame, &netif_data)!=ERR_OK) { - pbuf_free(received_frame); + if (netif->input(received_frame, netif) != ERR_OK) { + printf("ERROR: netif input failed\n"); + pbuf_free(received_frame); } received_frame = NULL; tud_network_recv_renew(); @@ -216,6 +241,28 @@ void tud_network_init_cb(void) { } } +static void handle_link_state_switch(void) { + /* Check for button press to toggle link state */ + static bool last_link_state = true; + static bool last_button_state = false; + bool current_button_state = board_button_read(); + + if (current_button_state && !last_button_state) { + /* Button pressed - toggle link state */ + last_link_state = !last_link_state; + if (last_link_state) { + printf("Link state: UP\n"); + netif_set_link_up(&netif_data); + } else { + printf("Link state: DOWN\n"); + netif_set_link_down(&netif_data); + } + /* LWIP callback will notify USB host about the change */ + } + last_button_state = current_button_state; + +} + int main(void) { /* initialize TinyUSB */ board_init(); @@ -243,15 +290,23 @@ int main(void) { lwiperf_start_tcp_server_default(NULL, NULL); #endif +#if CFG_TUD_NCM + printf("USB NCM network interface initialized\n"); +#elif CFG_TUD_ECM_RNDIS + printf("USB RNDIS/ECM network interface initialized\n"); +#endif + while (1) { tud_task(); service_traffic(); + handle_link_state_switch(); } return 0; } /* lwip has provision for using a mutex, when applicable */ +/* This implementation is for single-threaded use only */ sys_prot_t sys_arch_protect(void) { return 0; } diff --git a/examples/device/net_lwip_webserver/src/tusb_config.h b/examples/device/net_lwip_webserver/src/tusb_config.h index 22082fc81..c774f59ff 100644 --- a/examples/device/net_lwip_webserver/src/tusb_config.h +++ b/examples/device/net_lwip_webserver/src/tusb_config.h @@ -85,6 +85,7 @@ extern "C" { #endif // Use different configurations to test all net devices (also due to resource limitations) +#ifndef USE_ECM #if TU_CHECK_MCU(OPT_MCU_LPC15XX, OPT_MCU_LPC40XX, OPT_MCU_LPC51UXX, OPT_MCU_LPC54) #define USE_ECM 1 #elif TU_CHECK_MCU(OPT_MCU_SAMD21, OPT_MCU_SAML21, OPT_MCU_SAML22) @@ -97,6 +98,7 @@ extern "C" { #define USE_ECM 0 #define INCLUDE_IPERF #endif +#endif //-------------------------------------------------------------------- // NCM CLASS CONFIGURATION, SEE "ncm.h" FOR PERFORMANCE TUNING diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index f9fda0698..02833c5f1 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -110,6 +110,7 @@ typedef struct { NOTIFICATION_DONE } notification_xmit_state; // state of notification transmission bool notification_xmit_is_running; // notification is currently transmitted + bool link_is_up; // current link state // misc bool tud_network_recv_renew_active; // tud_network_recv_renew() is active (avoid recursive invocations) @@ -218,7 +219,7 @@ static void notification_xmit(uint8_t rhport, bool force_next) { .direction = TUSB_DIR_IN }, .bRequest = CDC_NOTIF_NETWORK_CONNECTION, - .wValue = 1 /* Connected */, + .wValue = ncm_interface.link_is_up ? 1 : 0, /* Dynamic link state */ .wIndex = ncm_interface.itf_num, .wLength = 0, }, @@ -232,6 +233,7 @@ static void notification_xmit(uint8_t rhport, bool force_next) { ncm_interface.notification_xmit_is_running = true; } else { TU_LOG_DRV(" NOTIFICATION_FINISHED\n"); + ncm_interface.notification_xmit_is_running = false; } } // notification_xmit @@ -755,6 +757,32 @@ static void tud_network_recv_renew_r(uint8_t rhport) { tud_network_recv_renew(); } // tud_network_recv_renew +/** + * Set the link state and send notification to host + */ +void tud_network_link_state(uint8_t rhport, bool is_up) { + TU_LOG_DRV("tud_network_link_state(%d, %d)\n", rhport, is_up); + + if (ncm_interface.link_is_up == is_up) { + // No change in link state + return; + } + + ncm_interface.link_is_up = is_up; + + // Only send notification if we have an active data interface + if (ncm_interface.itf_data_alt != 1) { + TU_LOG_DRV(" link state notification skipped (interface not active)\n"); + return; + } + + // Reset notification state to send link state update + ncm_interface.notification_xmit_state = NOTIFICATION_CONNECTED; + + // Trigger notification transmission + notification_xmit(rhport, false); +} + //----------------------------------------------------------------------------- // // all the netd_*() stuff (interface TinyUSB -> driver) @@ -774,6 +802,12 @@ void netd_init(void) { for (int i = 0; i < RECV_NTB_N; ++i) { ncm_interface.recv_free_ntb[i] = &ncm_epbuf.recv[i].ntb; } + // Default link state - can be configured via CFG_TUD_NCM_DEFAULT_LINK_UP + #ifdef CFG_TUD_NCM_DEFAULT_LINK_UP + ncm_interface.link_is_up = CFG_TUD_NCM_DEFAULT_LINK_UP; + #else + ncm_interface.link_is_up = true; // Default to link up if not set. + #endif } // netd_init /** diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 4c9a92f2d..fff2623b7 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -87,6 +87,11 @@ void tud_network_init_cb(void); // TODO removed later since it is not part of tinyusb stack extern uint8_t tud_network_mac_address[6]; +//------------- NCM -------------// + +// Set the network link state (up/down) and notify the host +void tud_network_link_state(uint8_t rhport, bool is_up); + //--------------------------------------------------------------------+ // INTERNAL USBD-CLASS DRIVER API //--------------------------------------------------------------------+ From 9021efcacb9d7380bce9d5c9e075b41cb8f28da5 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Tue, 27 May 2025 15:06:27 +1000 Subject: [PATCH 195/382] Add link state control support for ECM mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extends the link state control feature to CDC-ECM mode. RNDIS mode prints state changes but doesn't send notifications to the host yet (would require RNDIS_INDICATE_STATUS_MSG). For ECM: - Tracks link state and sends proper CDC notifications - Handles notification endpoint busy conditions - Only sends connection notification when link is actually up 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/class/net/ecm_rndis_device.c | 48 +++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/src/class/net/ecm_rndis_device.c b/src/class/net/ecm_rndis_device.c index a54e6d662..f1a88b3c0 100644 --- a/src/class/net/ecm_rndis_device.c +++ b/src/class/net/ecm_rndis_device.c @@ -81,6 +81,7 @@ typedef struct { static netd_interface_t _netd_itf; CFG_TUD_MEM_SECTION static netd_epbuf_t _netd_epbuf; static bool can_xmit; +static bool ecm_link_is_up = true; // Store link state for ECM mode void tud_network_recv_renew(void) { usbd_edpt_xfer(0, _netd_itf.ep_out, _netd_epbuf.rx, NETD_PACKET_SIZE); @@ -95,7 +96,11 @@ void netd_report(uint8_t *buf, uint16_t len) { const uint8_t rhport = 0; len = tu_min16(len, sizeof(ecm_notify_t)); - TU_VERIFY(usbd_edpt_claim(rhport, _netd_itf.ep_notif), ); + if (!usbd_edpt_claim(rhport, _netd_itf.ep_notif)) { + TU_LOG1("ECM: Failed to claim notification endpoint\n"); + return; + } + memcpy(_netd_epbuf.notify, buf, len); usbd_edpt_xfer(rhport, _netd_itf.ep_notif, _netd_epbuf.notify, len); } @@ -196,11 +201,11 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 } static void ecm_report(bool nc) { - const ecm_notify_t ecm_notify_nc = { + ecm_notify_t ecm_notify_nc = { .header = { .bmRequestType = 0xA1, .bRequest = 0, /* NETWORK_CONNECTION aka NetworkConnection */ - .wValue = 1, /* Connected */ + .wValue = ecm_link_is_up ? 1 : 0, /* Use current link state */ .wLength = 0, }, }; @@ -286,7 +291,10 @@ bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) { tud_control_xfer(rhport, request, NULL, 0); - ecm_report(true); + // Only send connection notification if link is up + if (ecm_link_is_up) { + ecm_report(true); + } } } else { if (request->bmRequestType_bit.direction == TUSB_DIR_IN) { @@ -363,9 +371,8 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } if (_netd_itf.ecm_mode && (ep_addr == _netd_itf.ep_notif)) { - if (sizeof(tusb_control_request_t) == xferred_bytes) { - ecm_report(false); - } + // Notification transfer complete - endpoint is now free + // Don't automatically send speed change notification after link state changes } return true; @@ -398,4 +405,31 @@ void tud_network_xmit(void *ref, uint16_t arg) { do_in_xfer(_netd_epbuf.tx, len); } +// Set the network link state (up/down) and notify the host +void tud_network_link_state(uint8_t rhport, bool is_up) { + (void)rhport; + + if (_netd_itf.ecm_mode) { + ecm_link_is_up = is_up; + + // For ECM mode, send network connection notification only + // Don't trigger speed change notification for link state changes + ecm_notify_t notify = { + .header = { + .bmRequestType = 0xA1, + .bRequest = 0, /* NETWORK_CONNECTION */ + .wValue = is_up ? 1 : 0, /* 0 = disconnected, 1 = connected */ + .wLength = 0, + }, + }; + notify.header.wIndex = _netd_itf.itf_num; + netd_report((uint8_t *)¬ify, sizeof(notify.header)); + } else { + // For RNDIS mode, we would need to implement RNDIS status indication + // This is more complex and requires RNDIS_INDICATE_STATUS_MSG + // For now, RNDIS doesn't support dynamic link state changes + (void)is_up; + } +} + #endif From b6ce41188e6780436dc9a9a0ed1232631753e3bb Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Tue, 27 May 2025 15:24:27 +1000 Subject: [PATCH 196/382] examples/device/net_lwip_webserver: Simplify example code. Now that tud_network_recv_renew has protections against recursion it's safe and simpler to handle the lwip frame entirely in the same callback. --- examples/device/net_lwip_webserver/src/main.c | 52 +++++-------------- 1 file changed, 14 insertions(+), 38 deletions(-) diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 41f02576f..4bdddf6c5 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -69,9 +69,6 @@ try changing the first byte of tud_network_mac_address[] below from 0x02 to 0x00 /* lwip context */ static struct netif netif_data; -/* shared between tud_network_recv_cb() and service_traffic() */ -static struct pbuf *received_frame; - /* this is used by this code, ./class/net/net_driver.c, and usb_descriptors.c */ /* ideally speaking, this should be generated from the hardware's unique ID (if available) */ /* it is suggested that the first byte is 0x02 to indicate a link-local address */ @@ -184,9 +181,7 @@ bool dns_query_proc(const char *name, ip4_addr_t *addr) { } bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { - /* this shouldn't happen, but if we get another packet before - parsing the previous, we must signal our inability to accept it */ - if (received_frame) return false; + struct netif *netif = &netif_data; if (size) { struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL); @@ -199,8 +194,16 @@ bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { /* Copy buf to pbuf */ pbuf_take(p, src, size); - /* store away the pointer for service_traffic() to later handle */ - received_frame = p; + // Surrender ownership of our pbuf unless there was an error + // Only call pbuf_free if not Ok else it will panic with "pbuf_free: p->ref > 0" + // or steal it from whatever took ownership of it with undefined consequences. + // See: https://savannah.nongnu.org/patch/index.php?10121 + if (netif->input(p, netif) != ERR_OK) { + printf("ERROR: netif input failed\n"); + pbuf_free(p); + } + // Signal tinyusb that the current frame has been processed. + tud_network_recv_renew(); } return true; @@ -214,39 +217,12 @@ uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) { return pbuf_copy_partial(p, dst, p->tot_len, 0); } -static void service_traffic(void) { - /* handle any packet received by tud_network_recv_cb() */ - if (received_frame) { - struct netif *netif = &netif_data; - // Surrender ownership of our pbuf unless there was an error - // Only call pbuf_free if not Ok else it will panic with "pbuf_free: p->ref > 0" - // or steal it from whatever took ownership of it with undefined consequences. - // See: https://savannah.nongnu.org/patch/index.php?10121 - if (netif->input(received_frame, netif) != ERR_OK) { - printf("ERROR: netif input failed\n"); - pbuf_free(received_frame); - } - received_frame = NULL; - tud_network_recv_renew(); - } - - sys_check_timeouts(); -} - -void tud_network_init_cb(void) { - /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ - if (received_frame) { - pbuf_free(received_frame); - received_frame = NULL; - } -} - static void handle_link_state_switch(void) { /* Check for button press to toggle link state */ static bool last_link_state = true; static bool last_button_state = false; bool current_button_state = board_button_read(); - + if (current_button_state && !last_button_state) { /* Button pressed - toggle link state */ last_link_state = !last_link_state; @@ -260,7 +236,7 @@ static void handle_link_state_switch(void) { /* LWIP callback will notify USB host about the change */ } last_button_state = current_button_state; - + } int main(void) { @@ -298,7 +274,7 @@ int main(void) { while (1) { tud_task(); - service_traffic(); + sys_check_timeouts(); // service lwip handle_link_state_switch(); } From 3d2b870fcb54f9d4f4e3e72678543ff936069f75 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 29 May 2025 13:36:34 +0200 Subject: [PATCH 197/382] Fix wrong SysTick clock on NUCLEO-C071RB Signed-off-by: HiFiPhile --- hw/bsp/stm32c0/boards/stm32c071nucleo/board.h | 36 +++++++++++++++++++ hw/bsp/stm32c0/family.c | 32 +++++------------ 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/hw/bsp/stm32c0/boards/stm32c071nucleo/board.h b/hw/bsp/stm32c0/boards/stm32c071nucleo/board.h index c7d809717..751df2251 100644 --- a/hw/bsp/stm32c0/boards/stm32c071nucleo/board.h +++ b/hw/bsp/stm32c0/boards/stm32c071nucleo/board.h @@ -55,9 +55,45 @@ // Enable UART serial communication with the ST-Link #define UART_DEV USART2 +#define UART_CLK_EN __HAL_RCC_USART2_CLK_ENABLE #define UART_GPIO_PORT GPIOA #define UART_GPIO_AF GPIO_AF1_USART2 #define UART_TX_PIN GPIO_PIN_2 #define UART_RX_PIN GPIO_PIN_3 +static inline void board_clock_init(void) { + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_CRSInitTypeDef RCC_CRSInitStruct = {0}; + + /* -1- Enable HSIUSB48 Oscillator */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* -2- Initializes the CPU, AHB and APB buses clocks */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSIUSB48; + RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1; + + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1); + + + __HAL_RCC_CRS_CLK_ENABLE(); + + // Configures CRS + RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1; + RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB; + RCC_CRSInitStruct.Polarity = RCC_CRS_SYNC_POLARITY_RISING; + RCC_CRSInitStruct.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000,1000); + RCC_CRSInitStruct.ErrorLimitValue = 34; + RCC_CRSInitStruct.HSI48CalibrationValue = 32; + + HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct); +} + #endif /* BOARD_H_ */ diff --git a/hw/bsp/stm32c0/family.c b/hw/bsp/stm32c0/family.c index ace3f2a71..09704b527 100644 --- a/hw/bsp/stm32c0/family.c +++ b/hw/bsp/stm32c0/family.c @@ -53,31 +53,16 @@ UART_HandleTypeDef UartHandle; void board_init(void) { HAL_Init(); - - // Enable the HSIUSB48 48 MHz oscillator. - RCC->CR |= RCC_CR_HSIUSB48ON; - - // Wait for HSIUSB48 to be ready. - while (!(RCC->CR & RCC_CR_HSIUSB48RDY)) { } - - // Change the SYSCLK source to HSIUSB48. - RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | RCC_SYSCLKSOURCE_HSIUSB48; - - // Wait for the SYSCLK source to change. - while ((RCC->CFGR & RCC_CFGR_SWS) >> RCC_CFGR_SWS_Pos != RCC_SYSCLKSOURCE_HSIUSB48) { } - - // Disable HSI48 to save power. - RCC->CR &= ~RCC_CR_HSION; + board_clock_init(); // Enable peripheral clocks. - RCC->APBENR1 = RCC_APBENR1_USBEN | RCC_APBENR1_CRSEN | RCC_APBENR1_USART2EN; - RCC->APBENR2 = RCC_APBENR2_USART1EN; - - // Enable all GPIO clocks. - RCC->IOPENR = 0x2F; - - // Turn on CRS to make the HSIUSB48 clock more precise when USB is connected. - CRS->CR |= CRS_CR_AUTOTRIMEN | CRS_CR_CEN; + __HAL_RCC_USB_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer @@ -109,6 +94,7 @@ void board_init(void) { } #ifdef UART_DEV + UART_CLK_EN(); // UART { GPIO_InitTypeDef gpio_init = { 0 }; From dc0038f6147584dce64323bb4895a3632c312bc1 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Thu, 29 May 2025 13:50:05 +0200 Subject: [PATCH 198/382] uac2: remove support fifo Signed-off-by: HiFiPhile --- .../device/audio_4_channel_mic/src/main.c | 35 - .../audio_4_channel_mic/src/tusb_config.h | 15 - .../audio_4_channel_mic_freertos/src/main.c | 35 - .../src/tusb_config.h | 15 - src/class/audio/audio_device.c | 888 ++---------------- src/class/audio/audio_device.h | 236 +---- 6 files changed, 82 insertions(+), 1142 deletions(-) diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index e8c40309e..f78e48f0c 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -69,13 +69,8 @@ uint8_t clkValid; audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state -#if CFG_TUD_AUDIO_ENABLE_ENCODING -// Audio test data, each buffer contains 2 channels, buffer[0] for CH0-1, buffer[1] for CH1-2 -uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000/CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; -#else // Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000]; -#endif void led_blinking_task(void); void audio_task(void); @@ -106,27 +101,6 @@ int main(void) sampleFreqRng.subrange[0].bRes = 0; // Generate dummy data -#if CFG_TUD_AUDIO_ENABLE_ENCODING - uint16_t * p_buff = i2s_dummy_buffer[0]; - uint16_t dataVal = 0; - for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) - { - // CH0 saw wave - *p_buff++ = dataVal; - // CH1 inverted saw wave - *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; - dataVal+= 32; - } - p_buff = i2s_dummy_buffer[1]; - for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) - { - // CH3 square wave - *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; - // CH4 sinus wave - float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); - *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); - } -#else uint16_t * p_buff = i2s_dummy_buffer; uint16_t dataVal = 0; for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) @@ -142,7 +116,6 @@ int main(void) float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); } -#endif while (1) { @@ -195,15 +168,7 @@ void audio_task(void) uint32_t curr_ms = board_millis(); if ( start_ms == curr_ms ) return; // not enough time start_ms = curr_ms; -#if CFG_TUD_AUDIO_ENABLE_ENCODING - // Write I2S buffer into FIFO - for (uint8_t cnt=0; cnt < 2; cnt++) - { - tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX); - } -#else tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); -#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/audio_4_channel_mic/src/tusb_config.h b/examples/device/audio_4_channel_mic/src/tusb_config.h index 46484f847..446a7a32a 100644 --- a/examples/device/audio_4_channel_mic/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic/src/tusb_config.h @@ -115,26 +115,11 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup #define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_ENABLE_ENCODING 1 #define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1 -#if CFG_TUD_AUDIO_ENABLE_ENCODING - -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN - -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 1 -#define CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX 2 // One I2S stream contains two channels, each stream is saved within one support FIFO - this value is currently fixed, the driver does not support a changing value -#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX) -#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) // Example write FIFO every 1ms, so it should be 8 times larger for HS device - -#else - #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device -#endif - #ifdef __cplusplus } #endif diff --git a/examples/device/audio_4_channel_mic_freertos/src/main.c b/examples/device/audio_4_channel_mic_freertos/src/main.c index c9de4029a..99278b5cc 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/main.c +++ b/examples/device/audio_4_channel_mic_freertos/src/main.c @@ -105,13 +105,8 @@ uint8_t clkValid; audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state -#if CFG_TUD_AUDIO_ENABLE_ENCODING -// Audio test data, each buffer contains 2 channels, buffer[0] for CH0-1, buffer[1] for CH1-2 -uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000/CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; -#else // Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000]; -#endif void led_blinking_task(void* param); void usb_device_task(void* param); @@ -132,27 +127,6 @@ int main(void) sampleFreqRng.subrange[0].bRes = 0; // Generate dummy data -#if CFG_TUD_AUDIO_ENABLE_ENCODING - uint16_t * p_buff = i2s_dummy_buffer[0]; - uint16_t dataVal = 0; - for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) - { - // CH0 saw wave - *p_buff++ = dataVal; - // CH1 inverted saw wave - *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; - dataVal+= 32; - } - p_buff = i2s_dummy_buffer[1]; - for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) - { - // CH3 square wave - *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; - // CH4 sinus wave - float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); - *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); - } -#else uint16_t * p_buff = i2s_dummy_buffer; uint16_t dataVal = 0; for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) @@ -168,7 +142,6 @@ int main(void) float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); } -#endif #if configSUPPORT_STATIC_ALLOCATION // blinky task @@ -269,15 +242,7 @@ void audio_task(void* param) // Here we simulate a I2S receive callback every 1ms. while (1) { vTaskDelay(1); -#if CFG_TUD_AUDIO_ENABLE_ENCODING - // Write I2S buffer into FIFO - for (uint8_t cnt=0; cnt < 2; cnt++) - { - tud_audio_write_support_ff(cnt, i2s_dummy_buffer[cnt], AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX); - } -#else tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); -#endif } } diff --git a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h index 5cd93b0d6..5ac51b153 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h @@ -121,26 +121,11 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 4 // This value is not required by the driver, it parses this information from the descriptor once the alternate interface is set by the host - we use it for the setup #define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_ENABLE_ENCODING 1 #define CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL 1 -#if CFG_TUD_AUDIO_ENABLE_ENCODING - -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_EP_SZ_IN - -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 1 -#define CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX 2 // One I2S stream contains two channels, each stream is saved within one support FIFO - this value is currently fixed, the driver does not support a changing value -#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO (CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX) -#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * (CFG_TUD_AUDIO_EP_SZ_IN / CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO) // Example write FIFO every 1ms, so it should be 8 times larger for HS device - -#else - #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device -#endif - #ifdef __cplusplus } #endif diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 7a6fd453f..11a3d4a73 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -108,19 +108,19 @@ #endif // Put swap buffer in USB section only if necessary -#if USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING +#if USE_LINEAR_BUFFER #define IN_SW_BUF_MEM_ATTR TU_ATTR_ALIGNED(4) #else #define IN_SW_BUF_MEM_ATTR CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN #endif -#if USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING +#if USE_LINEAR_BUFFER #define OUT_SW_BUF_MEM_ATTR TU_ATTR_ALIGNED(4) #else #define OUT_SW_BUF_MEM_ATTR CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN #endif // EP IN software buffers and mutexes -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_ENABLE_EP_IN tu_static IN_SW_BUF_MEM_ATTR struct { #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 TUD_EPBUF_DEF(buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ); @@ -144,12 +144,11 @@ tu_static IN_SW_BUF_MEM_ATTR struct { tu_static osal_mutex_def_t ep_in_ff_mutex_wr_3; #endif #endif -#endif// CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#endif// CFG_TUD_AUDIO_ENABLE_EP_IN // Linear buffer TX in case: // - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR -// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into -#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) +#if CFG_TUD_AUDIO_ENABLE_EP_IN && USE_LINEAR_BUFFER tu_static CFG_TUD_MEM_SECTION struct { #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX > 0 TUD_EPBUF_DEF(buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX); @@ -161,10 +160,10 @@ tu_static CFG_TUD_MEM_SECTION struct { TUD_EPBUF_DEF(buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SZ_MAX); #endif } lin_buf_in; -#endif// CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) +#endif// CFG_TUD_AUDIO_ENABLE_EP_IN && USE_LINEAR_BUFFER // EP OUT software buffers and mutexes -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_ENABLE_EP_OUT tu_static OUT_SW_BUF_MEM_ATTR struct { #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 TUD_EPBUF_DEF(buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ); @@ -188,12 +187,11 @@ tu_static OUT_SW_BUF_MEM_ATTR struct { tu_static osal_mutex_def_t ep_out_ff_mutex_rd_3; #endif #endif -#endif// CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#endif// CFG_TUD_AUDIO_ENABLE_EP_OUT // Linear buffer RX in case: // - target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR -// - the software encoding is used - in this case the linear buffers serve as a target memory where logical channels are encoded into -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && USE_LINEAR_BUFFER tu_static CFG_TUD_MEM_SECTION struct { #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX > 0 TUD_EPBUF_DEF(buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX); @@ -205,7 +203,7 @@ tu_static CFG_TUD_MEM_SECTION struct { TUD_EPBUF_DEF(buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SZ_MAX); #endif } lin_buf_out; -#endif// CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) +#endif// CFG_TUD_AUDIO_ENABLE_EP_OUT && USE_LINEAR_BUFFER // Control buffers tu_static CFG_TUD_MEM_SECTION struct { @@ -229,59 +227,6 @@ tu_static uint8_t alt_setting_2[CFG_TUD_AUDIO_FUNC_2_N_AS_INT]; tu_static uint8_t alt_setting_3[CFG_TUD_AUDIO_FUNC_3_N_AS_INT]; #endif -// Software encoding/decoding support FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - tu_static TU_ATTR_ALIGNED(4) uint8_t tx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ]; - tu_static tu_fifo_t tx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - tu_static osal_mutex_def_t tx_supp_ff_mutex_wr_1[CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO];// No need for read mutex as only USB driver reads from FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - tu_static TU_ATTR_ALIGNED(4) uint8_t tx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ]; - tu_static tu_fifo_t tx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - tu_static osal_mutex_def_t tx_supp_ff_mutex_wr_2[CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO];// No need for read mutex as only USB driver reads from FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - tu_static TU_ATTR_ALIGNED(4) uint8_t tx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ]; - tu_static tu_fifo_t tx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - tu_static osal_mutex_def_t tx_supp_ff_mutex_wr_3[CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO];// No need for read mutex as only USB driver reads from FIFO - #endif - #endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - #if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - tu_static TU_ATTR_ALIGNED(4) uint8_t rx_supp_ff_buf_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ]; - tu_static tu_fifo_t rx_supp_ff_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - tu_static osal_mutex_def_t rx_supp_ff_mutex_rd_1[CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO];// No need for write mutex as only USB driver writes into FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - tu_static TU_ATTR_ALIGNED(4) uint8_t rx_supp_ff_buf_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ]; - tu_static tu_fifo_t rx_supp_ff_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - tu_static osal_mutex_def_t rx_supp_ff_mutex_rd_2[CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO];// No need for write mutex as only USB driver writes into FIFO - #endif - #endif - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - tu_static TU_ATTR_ALIGNED(4) uint8_t rx_supp_ff_buf_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO][CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ]; - tu_static tu_fifo_t rx_supp_ff_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO]; - #if CFG_FIFO_MUTEX - tu_static osal_mutex_def_t rx_supp_ff_mutex_rd_3[CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO];// No need for write mutex as only USB driver writes into FIFO - #endif - #endif -#endif - // Aligned buffer for feedback EP #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP tu_static CFG_TUD_MEM_SECTION struct { @@ -363,19 +308,6 @@ typedef struct } feedback; #endif// CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -// Decoding parameters - parameters are set when alternate AS interface is set by host -// Coding is currently only supported for EP. Software coding corresponding to AS interfaces without EPs are not supported currently. -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - audio_format_type_t format_type_rx; - uint8_t n_channels_rx; - - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - audio_data_format_type_I_t format_type_I_rx; - uint8_t n_bytes_per_sample_rx; - uint8_t n_ff_used_rx; - #endif -#endif - #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL uint32_t sample_rate_tx; uint16_t packet_sz_tx[3]; @@ -384,15 +316,10 @@ typedef struct #endif // Encoding parameters - parameters are set when alternate AS interface is set by host -#if CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL) +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL audio_format_type_t format_type_tx; uint8_t n_channels_tx; uint8_t n_bytes_per_sample_tx; - - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio_data_format_type_I_t format_type_I_tx; - uint8_t n_ff_used_tx; - #endif #endif /*------------- From this point, data is not cleared by bus reset -------------*/ @@ -405,40 +332,21 @@ typedef struct uint8_t *alt_setting;// We need to save the current alternate setting this way, because it is possible that there are AS interfaces which do not have an EP! // EP Transfer buffers and FIFOs -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_ENABLE_EP_OUT tu_fifo_t ep_out_ff; #endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_ENABLE_EP_IN tu_fifo_t ep_in_ff; #endif -// Support FIFOs for software encoding and decoding -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - tu_fifo_t *rx_supp_ff; - uint8_t n_rx_supp_ff; - uint16_t rx_supp_ff_sz_max; - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - uint8_t n_channels_per_ff_rx; - #endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - tu_fifo_t *tx_supp_ff; - uint8_t n_tx_supp_ff; - uint16_t tx_supp_ff_sz_max; - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - uint8_t n_channels_per_ff_tx; - #endif -#endif - -// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically OR the support FIFOs are used -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) +// Linear buffer in case target MCU is not capable of handling a ring buffer FIFO e.g. no hardware buffer is available or driver is would need to be changed dramatically +#if CFG_TUD_AUDIO_ENABLE_EP_OUT && USE_LINEAR_BUFFER uint8_t *lin_buf_out; #define USE_LINEAR_BUFFER_RX 1 #endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_ENCODING) +#if CFG_TUD_AUDIO_ENABLE_EP_IN && USE_LINEAR_BUFFER uint8_t *lin_buf_in; #define USE_LINEAR_BUFFER_TX 1 #endif @@ -604,18 +512,10 @@ tu_static CFG_TUD_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t *audio, uint16_t n_bytes_received); #endif -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t *audio, uint16_t n_bytes_received); -#endif - #if CFG_TUD_AUDIO_ENABLE_EP_IN static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t *audio); #endif -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t *audio); -#endif - static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const *p_request); static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p_request); @@ -626,11 +526,8 @@ static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id); static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id); static uint8_t audiod_get_audio_fct_idx(audiod_function_t *audio); -#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING) -static void audiod_parse_for_AS_params(audiod_function_t *audio, uint8_t const *p_desc, uint8_t const *p_desc_end, uint8_t const as_itf); -#endif - #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL +static void audiod_parse_flow_control_params(audiod_function_t *audio, uint8_t const *p_desc); static bool audiod_calc_tx_packet_sz(audiod_function_t *audio); static uint16_t audiod_tx_packet_size(const uint16_t *norminal_size, uint16_t data_count, uint16_t fifo_depth, uint16_t max_size); #endif @@ -651,7 +548,7 @@ bool tud_audio_n_mounted(uint8_t func_id) { // READ API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_ENABLE_EP_OUT uint16_t tud_audio_n_available(uint8_t func_id) { TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); @@ -673,36 +570,7 @@ tu_fifo_t *tud_audio_n_get_ep_out_ff(uint8_t func_id) { return NULL; } -#endif - -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT -// Delete all content in the support RX FIFOs -bool tud_audio_n_clear_rx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_clear(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_available_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_count(&_audiod_fct[func_id].rx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_read_support_ff(uint8_t func_id, uint8_t ff_idx, void *buffer, uint16_t bufsize) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff); - return tu_fifo_read_n(&_audiod_fct[func_id].rx_supp_ff[ff_idx], buffer, bufsize); -} - -tu_fifo_t *tud_audio_n_get_rx_support_ff(uint8_t func_id, uint8_t ff_idx) { - if (func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_rx_supp_ff) return &_audiod_fct[func_id].rx_supp_ff[ff_idx]; - return NULL; -} -#endif - -// This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO (or support FIFOs + decoding of received stream into audio channels). -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_DECODING = 0. - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT - +// This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO. static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t *audio, uint16_t n_bytes_received) { uint8_t idxItf = 0; uint8_t const *dummy2; @@ -711,62 +579,24 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t *audio, uint16_t idx_audio_fct = audiod_get_audio_fct_idx(audio); TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); - // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO (or decoded into support RX software FIFO) + // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - #if CFG_TUD_AUDIO_ENABLE_DECODING - - switch (audio->format_type_rx) { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL DECODING PROCEDURE REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; - - case AUDIO_FORMAT_TYPE_I: - - switch (audio->format_type_I_rx) { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: - TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received)); - break; - - default: - // DESIRED CFG_TUD_AUDIO_FORMAT_TYPE_I_RX NOT IMPLEMENTED! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_RX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_RX not implemented!\r\n"); - TU_BREAKPOINT(); - break; - } - - // Prepare for next transmission - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); - - #else - - #if USE_LINEAR_BUFFER_RX + #if USE_LINEAR_BUFFER_RX // Data currently is in linear buffer, copy into EP OUT FIFO TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); // Schedule for next receive TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); - #else + #else // Data is already placed in EP FIFO, schedule for next receive TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_out, &audio->ep_out_ff, audio->ep_out_sz), false); - #endif + #endif - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP + #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP if (audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FIFO_COUNT) { audiod_fb_fifo_count_update(audio, tu_fifo_count(&audio->ep_out_ff)); } - #endif - #endif // Call a weak callback here - a possibility for user to get informed decoding was completed @@ -777,103 +607,11 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t *audio, uint16_t #endif//CFG_TUD_AUDIO_ENABLE_EP_OUT -// The following functions are used in case CFG_TUD_AUDIO_ENABLE_DECODING != 0 -#if CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_EP_OUT - -// Decoding according to 2.3.1.5 Audio Streams - -// Helper function -static inline void *audiod_interleaved_copy_bytes_fast_decode(uint16_t const nBytesPerSample, void *dst, const void *dst_end, void *src, uint8_t const n_ff_used) { - // Due to one FIFO contains 2 channels, data always aligned to (nBytesPerSample * 2) - uint16_t *dst16 = dst; - uint16_t *src16 = src; - const uint16_t *dst_end16 = dst_end; - uint32_t *dst32 = dst; - uint32_t *src32 = src; - const uint32_t *dst_end32 = dst_end; - - if (nBytesPerSample == 1) { - while (dst16 < dst_end16) { - *dst16++ = *src16++; - src16 += n_ff_used - 1; - } - return src16; - } else if (nBytesPerSample == 2) { - while (dst32 < dst_end32) { - *dst32++ = *src32++; - src32 += n_ff_used - 1; - } - return src32; - } else if (nBytesPerSample == 3) { - while (dst16 < dst_end16) { - *dst16++ = *src16++; - *dst16++ = *src16++; - *dst16++ = *src16++; - src16 += 3 * (n_ff_used - 1); - } - return src16; - } else// nBytesPerSample == 4 - { - while (dst32 < dst_end32) { - *dst32++ = *src32++; - *dst32++ = *src32++; - src32 += 2 * (n_ff_used - 1); - } - return src32; - } -} - -static bool audiod_decode_type_I_pcm(uint8_t rhport, audiod_function_t *audio, uint16_t n_bytes_received) { - (void) rhport; - - // Determine amount of samples - uint8_t const n_ff_used = audio->n_ff_used_rx; - uint16_t const nBytesPerFFToRead = n_bytes_received / n_ff_used; - uint8_t cnt_ff; - - // Decode - uint8_t *src; - uint8_t *dst_end; - - tu_fifo_buffer_info_t info; - - for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - tu_fifo_get_write_info(&audio->rx_supp_ff[cnt_ff], &info); - - if (info.len_lin != 0) { - info.len_lin = tu_min16(nBytesPerFFToRead, info.len_lin); - src = &audio->lin_buf_out[cnt_ff * audio->n_channels_per_ff_rx * audio->n_bytes_per_sample_rx]; - dst_end = info.ptr_lin + info.len_lin; - src = audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sample_rx, info.ptr_lin, dst_end, src, n_ff_used); - - // Handle wrapped part of FIFO - info.len_wrap = tu_min16(nBytesPerFFToRead - info.len_lin, info.len_wrap); - if (info.len_wrap != 0) { - dst_end = info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_decode(audio->n_bytes_per_sample_rx, info.ptr_wrap, dst_end, src, n_ff_used); - } - tu_fifo_advance_write_pointer(&audio->rx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); - } - } - - // Number of bytes should be a multiple of CFG_TUD_AUDIO_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_N_CHANNELS_RX but checking makes no sense - no way to correct it - // TU_VERIFY(cnt != n_bytes); - - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (audio->feedback.compute_method == AUDIO_FEEDBACK_METHOD_FIFO_COUNT) { - audiod_fb_fifo_count_update(audio, tu_fifo_count(&audio->rx_supp_ff[0])); - } - #endif - - return true; -} -#endif//CFG_TUD_AUDIO_ENABLE_DECODING - //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_ENABLE_EP_IN /** * \brief Write data to EP in buffer @@ -902,43 +640,47 @@ tu_fifo_t *tud_audio_n_get_ep_in_ff(uint8_t func_id) { return NULL; } -#endif +// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. +// n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. +static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t *audio) { + uint8_t idxItf; + uint8_t const *dummy2; -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN + uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio); + TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); -uint16_t tud_audio_n_flush_tx_support_ff(uint8_t func_id)// Force all content in the support TX FIFOs to be written into linear buffer and schedule a transmit -{ - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - audiod_function_t *audio = &_audiod_fct[func_id]; + // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications + if (audio->alt_setting[idxItf] == 0) return false; - uint16_t n_bytes_copied = tu_fifo_count(&audio->tx_supp_ff[0]); + // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or + // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). + TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - TU_VERIFY(audiod_tx_done_cb(audio->rhport, audio)); + // Send everything in ISO EP FIFO + uint16_t n_bytes_tx; - n_bytes_copied -= tu_fifo_count(&audio->tx_supp_ff[0]); - n_bytes_copied = n_bytes_copied * audio->tx_supp_ff[0].item_size; + #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + // packet_sz_tx is based on total packet size + n_bytes_tx = audiod_tx_packet_size(audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff), audio->ep_in_ff.depth, audio->ep_in_sz); + #else + n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz);// Limit up to max packet size, more can not be done for ISO + #endif + #if USE_LINEAR_BUFFER_TX + tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); + #else + // Send everything in ISO EP FIFO + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); + #endif - return n_bytes_copied; -} + // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame + TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); -bool tud_audio_n_clear_tx_support_ff(uint8_t func_id, uint8_t ff_idx) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); - return tu_fifo_clear(&_audiod_fct[func_id].tx_supp_ff[ff_idx]); -} - -uint16_t tud_audio_n_write_support_ff(uint8_t func_id, uint8_t ff_idx, const void *data, uint16_t len) { - TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff); - return tu_fifo_write_n(&_audiod_fct[func_id].tx_supp_ff[ff_idx], data, len); -} - -tu_fifo_t *tud_audio_n_get_tx_support_ff(uint8_t func_id, uint8_t ff_idx) { - if (func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL && ff_idx < _audiod_fct[func_id].n_tx_supp_ff) return &_audiod_fct[func_id].tx_supp_ff[ff_idx]; - return NULL; + return true; } #endif - #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP // If no interrupt transmit is pending bytes get written into buffer and a transmit is scheduled - once transmit completed tud_audio_int_done_cb() is called in inform user bool tud_audio_int_n_write(uint8_t func_id, const audio_interrupt_data_t *data) { @@ -962,223 +704,8 @@ bool tud_audio_int_n_write(uint8_t func_id, const audio_interrupt_data_t *data) } #endif -// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// If you prefer your own (more efficient) implementation suiting your purpose set CFG_TUD_AUDIO_ENABLE_ENCODING = 0 and use tud_audio_n_write. - -// n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -#if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t *audio) { - uint8_t idxItf; - uint8_t const *dummy2; - - uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio); - TU_VERIFY(audiod_get_AS_interface_index(audio->ep_in_as_intf_num, audio, &idxItf, &dummy2)); - - // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications - if (audio->alt_setting[idxItf] == 0) return false; - - // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or - // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - - // Send everything in ISO EP FIFO - uint16_t n_bytes_tx; - - // If support FIFOs are used, encode and schedule transmit - #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN - switch (audio->format_type_tx) { - case AUDIO_FORMAT_TYPE_UNDEFINED: - // INDIVIDUAL ENCODING PROCEDURE REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT encoding not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - - case AUDIO_FORMAT_TYPE_I: - - switch (audio->format_type_I_tx) { - case AUDIO_DATA_FORMAT_TYPE_I_PCM: - - n_bytes_tx = audiod_encode_type_I_pcm(rhport, audio); - break; - - default: - // YOUR ENCODING IS REQUIRED HERE! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_I_TX encoding not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - } - break; - - default: - // Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented! - TU_LOG2(" Desired CFG_TUD_AUDIO_FORMAT_TYPE_TX not implemented!\r\n"); - TU_BREAKPOINT(); - n_bytes_tx = 0; - break; - } - - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); - - #else - // No support FIFOs, if no linear buffer required schedule transmit, else put data into linear buffer and schedule - #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL - // packet_sz_tx is based on total packet size, here we want size for each support buffer. - n_bytes_tx = audiod_tx_packet_size(audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff), audio->ep_in_ff.depth, audio->ep_in_sz); - #else - n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz);// Limit up to max packet size, more can not be done for ISO - #endif - #if USE_LINEAR_BUFFER_TX - tu_fifo_read_n(&audio->ep_in_ff, audio->lin_buf_in, n_bytes_tx); - TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, n_bytes_tx)); - #else - // Send everything in ISO EP FIFO - TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); - #endif - - #endif - - // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - - return true; -} - -#endif//CFG_TUD_AUDIO_ENABLE_EP_IN - -#if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_EP_IN -// Take samples from the support buffer and encode them into the IN EP software FIFO -// Returns number of bytes written into linear buffer - -/* 2.3.1.7.1 PCM Format -The PCM (Pulse Coded Modulation) format is the most commonly used audio format to represent audio -data streams. The audio data is not compressed and uses a signed two’s-complement fixed point format. It -is left-justified (the sign bit is the Msb) and data is padded with trailing zeros to fill the remaining unused -bits of the subslot. The binary point is located to the right of the sign bit so that all values lie within the -range [-1, +1) - */ - -/* - * This function encodes channels saved within the support FIFOs into one stream by interleaving the PCM samples - * in the support FIFOs according to 2.3.1.5 Audio Streams. It does not control justification (left or right) and - * does not change the number of bytes per sample. - * */ - -// Helper function -static inline void *audiod_interleaved_copy_bytes_fast_encode(uint16_t const nBytesPerSample, void *src, const void *src_end, void *dst, uint8_t const n_ff_used) { - // Due to one FIFO contains 2 channels, data always aligned to (nBytesPerSample * 2) - uint16_t *dst16 = dst; - uint16_t *src16 = src; - const uint16_t *src_end16 = src_end; - uint32_t *dst32 = dst; - uint32_t *src32 = src; - const uint32_t *src_end32 = src_end; - - if (nBytesPerSample == 1) { - while (src16 < src_end16) { - *dst16++ = *src16++; - dst16 += n_ff_used - 1; - } - return dst16; - } else if (nBytesPerSample == 2) { - while (src32 < src_end32) { - *dst32++ = *src32++; - dst32 += n_ff_used - 1; - } - return dst32; - } else if (nBytesPerSample == 3) { - while (src16 < src_end16) { - *dst16++ = *src16++; - *dst16++ = *src16++; - *dst16++ = *src16++; - dst16 += 3 * (n_ff_used - 1); - } - return dst16; - } else// nBytesPerSample == 4 - { - while (src32 < src_end32) { - *dst32++ = *src32++; - *dst32++ = *src32++; - dst32 += 2 * (n_ff_used - 1); - } - return dst32; - } -} - -static uint16_t audiod_encode_type_I_pcm(uint8_t rhport, audiod_function_t *audio) { - // This function relies on the fact that the length of the support FIFOs was configured to be a multiple of the active sample size in bytes s.t. no sample is split within a wrap - // This is ensured within set_interface, where the FIFOs are reconfigured according to this size - - // We encode directly into IN EP's linear buffer - abort if previous transfer not complete - TU_VERIFY(!usbd_edpt_busy(rhport, audio->ep_in)); - - // Determine amount of samples - uint8_t const n_ff_used = audio->n_ff_used_tx; - uint16_t nBytesPerFFToSend = tu_fifo_count(&audio->tx_supp_ff[0]); - uint8_t cnt_ff; - - for (cnt_ff = 1; cnt_ff < n_ff_used; cnt_ff++) { - uint16_t const count = tu_fifo_count(&audio->tx_supp_ff[cnt_ff]); - if (count < nBytesPerFFToSend) { - nBytesPerFFToSend = count; - } - } - - #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL - const uint16_t norm_packet_sz_tx[3] = {audio->packet_sz_tx[0] / n_ff_used, - audio->packet_sz_tx[1] / n_ff_used, - audio->packet_sz_tx[2] / n_ff_used}; - // packet_sz_tx is based on total packet size, here we want size for each support buffer. - nBytesPerFFToSend = audiod_tx_packet_size(norm_packet_sz_tx, nBytesPerFFToSend, audio->tx_supp_ff[0].depth, audio->ep_in_sz / n_ff_used); - // Check if there is enough data - if (nBytesPerFFToSend == 0) return 0; - #else - // Check if there is enough data - if (nBytesPerFFToSend == 0) return 0; - // Limit to maximum sample number - THIS IS A POSSIBLE ERROR SOURCE IF TOO MANY SAMPLE WOULD NEED TO BE SENT BUT CAN NOT! - nBytesPerFFToSend = tu_min16(nBytesPerFFToSend, audio->ep_in_sz / n_ff_used); - // Round to full number of samples (flooring) - uint16_t const nSlotSize = audio->n_channels_per_ff_tx * audio->n_bytes_per_sample_tx; - nBytesPerFFToSend = (nBytesPerFFToSend / nSlotSize) * nSlotSize; - #endif - - // Encode - uint8_t *dst; - uint8_t *src_end; - - tu_fifo_buffer_info_t info; - - for (cnt_ff = 0; cnt_ff < n_ff_used; cnt_ff++) { - dst = &audio->lin_buf_in[cnt_ff * audio->n_channels_per_ff_tx * audio->n_bytes_per_sample_tx]; - - tu_fifo_get_read_info(&audio->tx_supp_ff[cnt_ff], &info); - - if (info.len_lin != 0) { - info.len_lin = tu_min16(nBytesPerFFToSend, info.len_lin);// Limit up to desired length - src_end = (uint8_t *) info.ptr_lin + info.len_lin; - dst = audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sample_tx, info.ptr_lin, src_end, dst, n_ff_used); - - // Limit up to desired length - info.len_wrap = tu_min16(nBytesPerFFToSend - info.len_lin, info.len_wrap); - - // Handle wrapped part of FIFO - if (info.len_wrap != 0) { - src_end = (uint8_t *) info.ptr_wrap + info.len_wrap; - audiod_interleaved_copy_bytes_fast_encode(audio->n_bytes_per_sample_tx, info.ptr_wrap, src_end, dst, n_ff_used); - } - - tu_fifo_advance_read_pointer(&audio->tx_supp_ff[cnt_ff], info.len_lin + info.len_wrap); - } - } - - return nBytesPerFFToSend * n_ff_used; -} -#endif//CFG_TUD_AUDIO_ENABLE_ENCODING - -// This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent - #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP +// This function is called once a transmit of a feedback packet was successfully completed. Here, we get the next feedback value to be sent static inline bool audiod_fb_send(audiod_function_t *audio) { bool apply_correction = (TUSB_SPEED_FULL == tud_speed_get()) && audio->feedback.format_correction; // Format the feedback value @@ -1260,7 +787,7 @@ void audiod_init(void) { } // Initialize IN EP FIFO if required -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_ENABLE_EP_IN switch (i) { #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 @@ -1288,7 +815,7 @@ void audiod_init(void) { break; #endif } -#endif// CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#endif// CFG_TUD_AUDIO_ENABLE_EP_IN // Initialize linear buffers #if USE_LINEAR_BUFFER_TX @@ -1312,7 +839,7 @@ void audiod_init(void) { #endif// USE_LINEAR_BUFFER_TX // Initialize OUT EP FIFO if required -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_ENABLE_EP_OUT switch (i) { #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 @@ -1340,7 +867,7 @@ void audiod_init(void) { break; #endif } -#endif// CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#endif// CFG_TUD_AUDIO_ENABLE_EP_OUT // Initialize linear buffers #if USE_LINEAR_BUFFER_RX @@ -1382,150 +909,6 @@ void audiod_init(void) { #endif } #endif// CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - - // Initialize TX support FIFOs if required -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - switch (i) { - #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->tx_supp_ff = tx_supp_ff_1; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO; cnt++) { - tu_fifo_config(&tx_supp_ff_1[cnt], tx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_1[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_1[cnt]), NULL); - #endif - } - - break; - #endif// CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->tx_supp_ff = tx_supp_ff_2; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO; cnt++) { - tu_fifo_config(&tx_supp_ff_2[cnt], tx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_2[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_2[cnt]), NULL); - #endif - } - - break; - #endif// CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->tx_supp_ff = tx_supp_ff_3; - audio->n_tx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; - audio->tx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO; cnt++) { - tu_fifo_config(&tx_supp_ff_3[cnt], tx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&tx_supp_ff_3[cnt], osal_mutex_create(&tx_supp_ff_mutex_wr_3[cnt]), NULL); - #endif - } - - break; - #endif// CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - } -#endif// CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - // Set encoding parameters for Type_I formats -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - switch (i) { - #if CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX; - break; - #endif - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX; - break; - #endif - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->n_channels_per_ff_tx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX; - break; - #endif - } -#endif// CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - - // Initialize RX support FIFOs if required -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - - switch (i) { - #if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->rx_supp_ff = rx_supp_ff_1; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO; cnt++) { - tu_fifo_config(&rx_supp_ff_1[cnt], rx_supp_ff_buf_1[cnt], CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_1[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_1[cnt]), NULL); - #endif - } - - break; - #endif// CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->rx_supp_ff = rx_supp_ff_2; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO; cnt++) { - tu_fifo_config(&rx_supp_ff_2[cnt], rx_supp_ff_buf_2[cnt], CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_2[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_2[cnt]), NULL); - #endif - } - - break; - #endif// CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->rx_supp_ff = rx_supp_ff_3; - audio->n_rx_supp_ff = CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; - audio->rx_supp_ff_sz_max = CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ; - for (uint8_t cnt = 0; cnt < CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO; cnt++) { - tu_fifo_config(&rx_supp_ff_3[cnt], rx_supp_ff_buf_3[cnt], CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&rx_supp_ff_3[cnt], osal_mutex_create(&rx_supp_ff_mutex_rd_3[cnt]), NULL); - #endif - } - - break; - #endif// CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - } -#endif// CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - - // Set encoding parameters for Type_I formats -#if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - switch (i) { - #if CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ > 0 - case 0: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX; - break; - #endif - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ > 0 - case 1: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX; - break; - #endif - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ > 0 - case 2: - audio->n_channels_per_ff_rx = CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX; - break; - #endif - } -#endif// CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING } } @@ -1540,25 +923,13 @@ void audiod_reset(uint8_t rhport) { audiod_function_t *audio = &_audiod_fct[i]; tu_memclr(audio, ITF_MEM_RESET_SIZE); -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_ENABLE_EP_IN tu_fifo_clear(&audio->ep_in_ff); #endif -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_ENABLE_EP_OUT tu_fifo_clear(&audio->ep_out_ff); #endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } -#endif } } @@ -1783,13 +1154,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p #endif // Clear FIFOs, since data is no longer valid - #if !CFG_TUD_AUDIO_ENABLE_ENCODING tu_fifo_clear(&audio->ep_in_ff); - #else - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) { - tu_fifo_clear(&audio->tx_supp_ff[cnt]); - } - #endif // Invoke callback - can be used to stop data sampling TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); @@ -1812,13 +1177,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p #endif // Clear FIFOs, since data is no longer valid - #if !CFG_TUD_AUDIO_ENABLE_DECODING tu_fifo_clear(&audio->ep_out_ff); - #else - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) { - tu_fifo_clear(&audio->rx_supp_ff[cnt]); - } - #endif // Invoke callback - can be used to stop data sampling TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); @@ -1848,7 +1207,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p while (p_desc_end - p_desc > 0) { // Find correct interface if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *) p_desc)->bInterfaceNumber == itf && ((tusb_desc_interface_t const *) p_desc)->bAlternateSetting == alt) { -#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING) +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL uint8_t const *p_desc_parse_for_params = p_desc; #endif // From this point forward follow the EP descriptors associated to the current alternate setting interface - Open EPs if necessary @@ -1875,21 +1234,10 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p audio->ep_in_as_intf_num = itf; audio->ep_in_sz = tu_edpt_packet_size(desc_ep); - // If software encoding is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters - #if CFG_TUD_AUDIO_ENABLE_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL - audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); - - // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap - #if CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - const uint16_t active_fifo_depth = (uint16_t) ((audio->tx_supp_ff_sz_max / (audio->n_channels_per_ff_tx * audio->n_bytes_per_sample_tx)) * (audio->n_channels_per_ff_tx * audio->n_bytes_per_sample_tx)); - for (uint8_t cnt = 0; cnt < audio->n_tx_supp_ff; cnt++) { - tu_fifo_config(&audio->tx_supp_ff[cnt], audio->tx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); - } - audio->n_ff_used_tx = audio->n_channels_tx / audio->n_channels_per_ff_tx; - TU_ASSERT(audio->n_ff_used_tx <= audio->n_tx_supp_ff); - #endif + // If flow control is enabled, parse for the corresponding parameters - doing this here means only AS interfaces with EPs get scanned for parameters + #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL + audiod_parse_flow_control_params(audio, p_desc_parse_for_params); #endif - // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); @@ -1897,7 +1245,6 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p #endif// CFG_TUD_AUDIO_ENABLE_EP_IN #if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT)// Checking usage not necessary { // Save address @@ -1905,20 +1252,6 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p audio->ep_out_as_intf_num = itf; audio->ep_out_sz = tu_edpt_packet_size(desc_ep); - #if CFG_TUD_AUDIO_ENABLE_DECODING - audiod_parse_for_AS_params(audio, p_desc_parse_for_params, p_desc_end, itf); - - // Reconfigure size of support FIFOs - this is necessary to avoid samples to get split in case of a wrap - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - const uint16_t active_fifo_depth = (audio->rx_supp_ff_sz_max / audio->n_bytes_per_sample_rx) * audio->n_bytes_per_sample_rx; - for (uint8_t cnt = 0; cnt < audio->n_rx_supp_ff; cnt++) { - tu_fifo_config(&audio->rx_supp_ff[cnt], audio->rx_supp_ff[cnt].buffer, active_fifo_depth, 1, true); - } - audio->n_ff_used_rx = audio->n_channels_rx / audio->n_channels_per_ff_rx; - TU_ASSERT(audio->n_ff_used_rx <= audio->n_rx_supp_ff); - #endif - #endif - // Prepare for incoming data #if USE_LINEAR_BUFFER_RX TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); @@ -1971,12 +1304,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: { // Initialize the threshold level to half filled - uint16_t fifo_lvl_thr; - #if CFG_TUD_AUDIO_ENABLE_DECODING - fifo_lvl_thr = tu_fifo_depth(&audio->rx_supp_ff[0]) / 2; - #else - fifo_lvl_thr = tu_fifo_depth(&audio->ep_out_ff) / 2; - #endif + uint16_t fifo_lvl_thr = tu_fifo_depth(&audio->ep_out_ff) / 2; audio->feedback.compute.fifo_count.fifo_lvl_thr = fifo_lvl_thr; audio->feedback.compute.fifo_count.fifo_lvl_avg = ((uint32_t) fifo_lvl_thr) << 16; // Avoid 64bit division @@ -2555,86 +1883,22 @@ static bool audiod_verify_ep_exists(uint8_t ep, uint8_t *func_id) { return false; } -#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING) -// p_desc points to the AS interface of alternate setting zero -// itf is the interface number of the corresponding interface - we check if the interface belongs to EP in or EP out to see if it is a TX or RX parameter -// Currently, only AS interfaces with an EP (in or out) are supposed to be parsed for! -static void audiod_parse_for_AS_params(audiod_function_t *audio, uint8_t const *p_desc, uint8_t const *p_desc_end, uint8_t const as_itf) { - #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) return;// Abort, this interface has no EP, this driver does not support this currently - #endif - #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num) return; - #endif - #if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_out_as_intf_num) return; - #endif +#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL +static void audiod_parse_flow_control_params(audiod_function_t *audio, uint8_t const *p_desc) { p_desc = tu_desc_next(p_desc);// Exclude standard AS interface descriptor of current alternate interface descriptor - // Condition modified from p_desc < p_desc_end to prevent gcc>=12 strict-overflow warning - while (p_desc_end - p_desc > 0) { - // Abort if follow up descriptor is a new standard interface descriptor - indicates the last AS descriptor was already finished - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) break; - - // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) { - #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (as_itf == audio->ep_in_as_intf_num) { - audio->n_channels_tx = ((audio_desc_cs_as_interface_t const *) p_desc)->bNrChannels; - audio->format_type_tx = (audio_format_type_t) (((audio_desc_cs_as_interface_t const *) p_desc)->bFormatType); - - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING - audio->format_type_I_tx = (audio_data_format_type_I_t) (((audio_desc_cs_as_interface_t const *) p_desc)->bmFormats); - #endif - } - #endif - - #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - if (as_itf == audio->ep_out_as_intf_num) { - audio->n_channels_rx = ((audio_desc_cs_as_interface_t const *) p_desc)->bNrChannels; - audio->format_type_rx = ((audio_desc_cs_as_interface_t const *) p_desc)->bFormatType; - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - audio->format_type_I_rx = ((audio_desc_cs_as_interface_t const *) p_desc)->bmFormats; - #endif - } - #endif - } + // Look for a Class-Specific AS Interface Descriptor(4.9.2) to verify format type and format and also to get number of physical channels + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_AS_GENERAL) { + audio->n_channels_tx = ((audio_desc_cs_as_interface_t const *) p_desc)->bNrChannels; + audio->format_type_tx = (audio_format_type_t) (((audio_desc_cs_as_interface_t const *) p_desc)->bFormatType); // Look for a Type I Format Type Descriptor(2.3.1.6 - Audio Formats) - #if CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING || CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING - if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const *) p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) { - #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num && as_itf != audio->ep_out_as_intf_num) break;// Abort loop, this interface has no EP, this driver does not support this currently - #endif - #if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_in_as_intf_num) break; - #endif - #if !CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_EP_OUT - if (as_itf != audio->ep_out_as_intf_num) break; - #endif - - #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (as_itf == audio->ep_in_as_intf_num) { - audio->n_bytes_per_sample_tx = ((audio_desc_type_I_format_t const *) p_desc)->bSubslotSize; - } - #endif - - #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - if (as_itf == audio->ep_out_as_intf_num) { - audio->n_bytes_per_sample_rx = ((audio_desc_type_I_format_t const *) p_desc)->bSubslotSize; - } - #endif - } - #endif - - // Other format types are not supported yet - p_desc = tu_desc_next(p_desc); + if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AS_INTERFACE_FORMAT_TYPE && ((audio_desc_type_I_format_t const *) p_desc)->bFormatType == AUDIO_FORMAT_TYPE_I) { + audio->n_bytes_per_sample_tx = ((audio_desc_type_I_format_t const *) p_desc)->bSubslotSize; + } } } -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL static bool audiod_calc_tx_packet_sz(audiod_function_t *audio) { TU_VERIFY(audio->format_type_tx == AUDIO_FORMAT_TYPE_I); diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 0a7bff212..603535b2a 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -206,153 +206,6 @@ // Audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74) #define CFG_TUD_AUDIO_INTERRUPT_EP_SZ 6 -// Use software encoding/decoding - -// The software coding feature of the driver is not mandatory. It is useful if, for instance, you have two I2S streams which need to be interleaved -// into a single PCM stream as SAMPLE_1 | SAMPLE_2 | SAMPLE_3 | SAMPLE_4. -// -// Currently, only PCM type I encoding/decoding is supported! -// -// If the coding feature is to be used, support FIFOs need to be configured. Their sizes and numbers are defined below. - -// Encoding/decoding is done in software and thus time consuming. If you can encode/decode your stream more efficiently do not use the -// support FIFOs but write/read directly into/from the EP_X_SW_BUFFER_FIFOs using -// - tud_audio_n_write() or -// - tud_audio_n_read(). -// To write/read to/from the support FIFOs use -// - tud_audio_n_write_support_ff() or -// - tud_audio_n_read_support_ff(). -// -// The encoding/decoding format type done is defined below. -// -// The encoding/decoding starts when the private callback functions -// - audio_tx_done_cb() -// - audio_rx_done_cb() -// are invoked. If support FIFOs are used, the corresponding encoding/decoding functions are called from there. -// Once encoding/decoding is done the result is put directly into the EP_X_SW_BUFFER_FIFOs. You can use the public callback functions -// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() -// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() -// if you want to get informed what happened. -// -// If you don't use the support FIFOs you may use the public callback functions -// - tud_audio_tx_done_pre_load_cb() or tud_audio_tx_done_post_load_cb() -// - tud_audio_rx_done_pre_read_cb() or tud_audio_rx_done_post_read_cb() -// to write/read from/into the EP_X_SW_BUFFER_FIFOs at the right time. -// -// If you need a different encoding which is not support so far implement it in the -// - audio_tx_done_cb() -// - audio_rx_done_cb() -// functions. - -// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size -// The actual coding parameters of active AS alternate interface is parsed from the descriptors - -// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple -// of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sample_sz) * sample_sz)! -// This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!! - -// For PCM encoding/decoding - -#ifndef CFG_TUD_AUDIO_ENABLE_ENCODING -#define CFG_TUD_AUDIO_ENABLE_ENCODING 0 -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_DECODING -#define CFG_TUD_AUDIO_ENABLE_DECODING 0 -#endif - -// This enabling allows to save the current coding parameters e.g. # of bytes per sample etc. - TYPE_I includes common PCM encoding -#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING 0 -#endif - -#ifndef CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING -#define CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING 0 -#endif - -// Type I Coding parameters not given within UAC2 descriptors -// It would be possible to allow for a more flexible setting and not fix this parameter as done below. However, this is most often not needed and kept for later if really necessary. The more flexible setting could be implemented within set_interface(), however, how the values are saved per alternate setting is to be determined! -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_ENCODING -#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_TX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING && CFG_TUD_AUDIO_ENABLE_TYPE_I_DECODING -#ifndef CFG_TUD_AUDIO_FUNC_1_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#if CFG_TUD_AUDIO > 1 -#ifndef CFG_TUD_AUDIO_FUNC_2_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#if CFG_TUD_AUDIO > 2 -#ifndef CFG_TUD_AUDIO_FUNC_3_CHANNEL_PER_FIFO_RX -#error You must tell the driver the number of channels per FIFO for the interleaved encoding! E.g. for an I2S interface having two channels, CHANNEL_PER_FIFO = 2 as the I2S stream having two channels is usually saved within one FIFO -#endif -#endif -#endif - -// Remaining types not support so far - -// Number of support FIFOs to set up - multiple channels can be handled by one FIFO - very common is two channels per FIFO stemming from one I2S interface -#ifndef CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_1_N_TX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_2_N_TX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_3_N_TX_SUPP_SW_FIFO 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_1_N_RX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_2_N_RX_SUPP_SW_FIFO 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO -#define CFG_TUD_AUDIO_FUNC_3_N_RX_SUPP_SW_FIFO 0 -#endif - -// Size of support FIFOs IN BYTES - if size > 0 there are as many FIFOs set up as CFG_TUD_AUDIO_FUNC_X_N_TX_SUPP_SW_FIFO and CFG_TUD_AUDIO_FUNC_X_N_RX_SUPP_SW_FIFO -#ifndef CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_1_TX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of TX channels) / (# of TX support FIFOs) * max(# of bytes per sample) -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_2_TX_SUPP_SW_FIFO_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_3_TX_SUPP_SW_FIFO_SZ 0 -#endif - -#ifndef CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_1_RX_SUPP_SW_FIFO_SZ 0 // FIFO size - minimum size: ceil(f_s/1000) * max(# of RX channels) / (# of RX support FIFOs) * max(# of bytes per sample) -#endif -#ifndef CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_2_RX_SUPP_SW_FIFO_SZ 0 -#endif -#ifndef CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ -#define CFG_TUD_AUDIO_FUNC_3_RX_SUPP_SW_FIFO_SZ 0 -#endif - -//static_assert(sizeof(tud_audio_desc_lengths) != CFG_TUD_AUDIO, "Supply audio function descriptor pack length!"); - -// Supported types of this driver: -// AUDIO_DATA_FORMAT_TYPE_I_PCM - Required definitions: CFG_TUD_AUDIO_N_CHANNELS and CFG_TUD_AUDIO_BYTES_PER_CHANNEL - #ifdef __cplusplus extern "C" { #endif @@ -368,38 +221,23 @@ extern "C" { //--------------------------------------------------------------------+ bool tud_audio_n_mounted (uint8_t func_id); -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_ENABLE_EP_OUT uint16_t tud_audio_n_available (uint8_t func_id); uint16_t tud_audio_n_read (uint8_t func_id, void* buffer, uint16_t bufsize); bool tud_audio_n_clear_ep_out_ff (uint8_t func_id); // Delete all content in the EP OUT FIFO tu_fifo_t* tud_audio_n_get_ep_out_ff (uint8_t func_id); #endif -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -bool tud_audio_n_clear_rx_support_ff (uint8_t func_id, uint8_t ff_idx); // Delete all content in the support RX FIFOs -uint16_t tud_audio_n_available_support_ff (uint8_t func_id, uint8_t ff_idx); -uint16_t tud_audio_n_read_support_ff (uint8_t func_id, uint8_t ff_idx, void* buffer, uint16_t bufsize); -tu_fifo_t* tud_audio_n_get_rx_support_ff (uint8_t func_id, uint8_t ff_idx); -#endif - -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_ENABLE_EP_IN uint16_t tud_audio_n_write (uint8_t func_id, const void * data, uint16_t len); bool tud_audio_n_clear_ep_in_ff (uint8_t func_id); // Delete all content in the EP IN FIFO tu_fifo_t* tud_audio_n_get_ep_in_ff (uint8_t func_id); #endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -uint16_t tud_audio_n_flush_tx_support_ff (uint8_t func_id); // Force all content in the support TX FIFOs to be written into EP SW FIFO -bool tud_audio_n_clear_tx_support_ff (uint8_t func_id, uint8_t ff_idx); -uint16_t tud_audio_n_write_support_ff (uint8_t func_id, uint8_t ff_idx, const void * data, uint16_t len); -tu_fifo_t* tud_audio_n_get_tx_support_ff (uint8_t func_id, uint8_t ff_idx); -#endif - #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP bool tud_audio_int_n_write (uint8_t func_id, const audio_interrupt_data_t * data); #endif - //--------------------------------------------------------------------+ // Application API (Interface0) //--------------------------------------------------------------------+ @@ -408,35 +246,21 @@ static inline bool tud_audio_mounted (void); // RX API -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_ENABLE_EP_OUT static inline uint16_t tud_audio_available (void); static inline bool tud_audio_clear_ep_out_ff (void); // Delete all content in the EP OUT FIFO static inline uint16_t tud_audio_read (void* buffer, uint16_t bufsize); static inline tu_fifo_t* tud_audio_get_ep_out_ff (void); #endif -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING -static inline bool tud_audio_clear_rx_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_available_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_read_support_ff (uint8_t ff_idx, void* buffer, uint16_t bufsize); -static inline tu_fifo_t* tud_audio_get_rx_support_ff (uint8_t ff_idx); -#endif - // TX API -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_ENABLE_EP_IN static inline uint16_t tud_audio_write (const void * data, uint16_t len); static inline bool tud_audio_clear_ep_in_ff (void); static inline tu_fifo_t* tud_audio_get_ep_in_ff (void); #endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING -static inline uint16_t tud_audio_flush_tx_support_ff (void); -static inline uint16_t tud_audio_clear_tx_support_ff (uint8_t ff_idx); -static inline uint16_t tud_audio_write_support_ff (uint8_t ff_idx, const void * data, uint16_t len); -static inline tu_fifo_t* tud_audio_get_tx_support_ff (uint8_t ff_idx); -#endif - // INT CTR API #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP @@ -593,7 +417,7 @@ static inline bool tud_audio_mounted(void) // RX API -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && !CFG_TUD_AUDIO_ENABLE_DECODING +#if CFG_TUD_AUDIO_ENABLE_EP_OUT static inline uint16_t tud_audio_available(void) { @@ -617,33 +441,9 @@ static inline tu_fifo_t* tud_audio_get_ep_out_ff(void) #endif -#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING - -static inline bool tud_audio_clear_rx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_clear_rx_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_available_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_available_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_read_support_ff(uint8_t ff_idx, void* buffer, uint16_t bufsize) -{ - return tud_audio_n_read_support_ff(0, ff_idx, buffer, bufsize); -} - -static inline tu_fifo_t* tud_audio_get_rx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_get_rx_support_ff(0, ff_idx); -} - -#endif - // TX API -#if CFG_TUD_AUDIO_ENABLE_EP_IN && !CFG_TUD_AUDIO_ENABLE_ENCODING +#if CFG_TUD_AUDIO_ENABLE_EP_IN static inline uint16_t tud_audio_write(const void * data, uint16_t len) { @@ -662,30 +462,6 @@ static inline tu_fifo_t* tud_audio_get_ep_in_ff(void) #endif -#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_ENABLE_ENCODING - -static inline uint16_t tud_audio_flush_tx_support_ff(void) -{ - return tud_audio_n_flush_tx_support_ff(0); -} - -static inline uint16_t tud_audio_clear_tx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_clear_tx_support_ff(0, ff_idx); -} - -static inline uint16_t tud_audio_write_support_ff(uint8_t ff_idx, const void * data, uint16_t len) -{ - return tud_audio_n_write_support_ff(0, ff_idx, data, len); -} - -static inline tu_fifo_t* tud_audio_get_tx_support_ff(uint8_t ff_idx) -{ - return tud_audio_n_get_tx_support_ff(0, ff_idx); -} - -#endif - #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP static inline bool tud_audio_int_write(const audio_interrupt_data_t * data) { From 56c9521abdef663b455a345c99a4f6b22591aa56 Mon Sep 17 00:00:00 2001 From: James Sandison Date: Wed, 4 Jun 2025 11:21:27 +1000 Subject: [PATCH 199/382] chore: squash previous commits from other branches --- docs/reference/boards.rst | 2 + docs/reference/dependencies.rst | 1 + .../build_system/cmake/cpu/cortex-m55.cmake | 26 + examples/build_system/make/cpu/cortex-m55.mk | 28 + examples/device/net_lwip_webserver/skip.txt | 1 + examples/host/bare_api/only.txt | 1 + examples/host/cdc_msc_hid/only.txt | 1 + examples/host/cdc_msc_hid_freertos/only.txt | 1 + examples/host/device_info/only.txt | 1 + examples/host/hid_controller/only.txt | 1 + examples/host/midi_rx/only.txt | 1 + examples/host/msc_file_explorer/only.txt | 1 + .../stm32n6/FreeRTOSConfig/FreeRTOSConfig.h | 149 ++ .../STM32N657XX_AXISRAM2_fsbl.ld | 203 ++ .../boards/stm32n657nucleo/board.cmake | 25 + hw/bsp/stm32n6/boards/stm32n657nucleo/board.h | 283 +++ .../stm32n6/boards/stm32n657nucleo/board.mk | 23 + .../stm32n657nucleo/tcpp0203/LICENSE.txt | 6 + .../tcpp0203/Release_Notes.html | 205 ++ .../tcpp0203/_htmresc/favicon.png | Bin 0 -> 4126 bytes .../tcpp0203/_htmresc/mini-st_2020.css | 1703 +++++++++++++++++ .../tcpp0203/_htmresc/st_logo_2020.png | Bin 0 -> 7520 bytes .../stm32n657nucleo/tcpp0203/tcpp0203.c | 886 +++++++++ .../stm32n657nucleo/tcpp0203/tcpp0203.h | 353 ++++ .../stm32n657nucleo/tcpp0203/tcpp0203_reg.c | 73 + .../stm32n657nucleo/tcpp0203/tcpp0203_reg.h | 98 + hw/bsp/stm32n6/family.c | 276 +++ hw/bsp/stm32n6/family.cmake | 147 ++ hw/bsp/stm32n6/family.mk | 101 + hw/bsp/stm32n6/partition_stm32n657xx.h | 792 ++++++++ hw/bsp/stm32n6/stm32n6xx_hal_conf.h | 504 +++++ hw/bsp/zephyr_board_aliases.cmake | 1 + src/common/tusb_mcu.h | 9 + src/portable/synopsys/dwc2/dcd_dwc2.c | 5 + src/portable/synopsys/dwc2/dwc2_info.py | 1 + src/portable/synopsys/dwc2/dwc2_stm32.h | 11 + src/portable/synopsys/dwc2/hcd_dwc2.c | 4 + src/tusb_option.h | 1 + tools/get_deps.py | 8 +- 39 files changed, 5931 insertions(+), 1 deletion(-) create mode 100644 examples/build_system/cmake/cpu/cortex-m55.cmake create mode 100644 examples/build_system/make/cpu/cortex-m55.mk create mode 100644 hw/bsp/stm32n6/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/STM32N657XX_AXISRAM2_fsbl.ld create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/board.h create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/LICENSE.txt create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/Release_Notes.html create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/favicon.png create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/mini-st_2020.css create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/st_logo_2020.png create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.c create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.h create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.c create mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.h create mode 100644 hw/bsp/stm32n6/family.c create mode 100644 hw/bsp/stm32n6/family.cmake create mode 100644 hw/bsp/stm32n6/family.mk create mode 100644 hw/bsp/stm32n6/partition_stm32n657xx.h create mode 100644 hw/bsp/stm32n6/stm32n6xx_hal_conf.h diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 5786b2182..317a40c9c 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -269,6 +269,8 @@ stm32l412nucleo STM32 L412 Nucleo stm32l4 https://www.st stm32l476disco STM32 L476 Disco stm32l4 https://www.st.com/en/evaluation-tools/32l476gdiscovery.html stm32l4p5nucleo STM32 L4P5 Nucleo stm32l4 https://www.st.com/en/evaluation-tools/nucleo-l4p5zg.html stm32l4r5nucleo STM32 L4R5 Nucleo stm32l4 https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html +stm32n657_dk STM32 N657 Discovery Kit stm32n6 https://www.st.com/en/evaluation-tools/stm32n6570-dk.html +stm32n657nucleo STM32 N657 Nucleo stm32n6 https://www.st.com/en/evaluation-tools/nucleo-n657x0-q.html b_u585i_iot2a STM32 B-U585i IOT2A Discovery kit stm32u5 https://www.st.com/en/evaluation-tools/b-u585i-iot02a.html stm32u545nucleo STM32 U545 Nucleo stm32u5 https://www.st.com/en/evaluation-tools/nucleo-u545re-q.html stm32u575eval STM32 U575 Eval stm32u5 https://www.st.com/en/evaluation-tools/stm32u575i-ev.html diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index e124466da..98545b4cf 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -57,6 +57,7 @@ hw/mcu/st/stm32l0xx_hal_driver https://github.com/STMicroelectronics/ hw/mcu/st/stm32l1xx_hal_driver https://github.com/STMicroelectronics/stm32l1xx_hal_driver.git 44efc446fa69ed8344e7fd966e68ed11043b35d9 stm32l1 hw/mcu/st/stm32l4xx_hal_driver https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git aee3d5bf283ae5df87532b781bdd01b7caf256fc stm32l4 hw/mcu/st/stm32l5xx_hal_driver https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git 675c32a75df37f39d50d61f51cb0dcf53f07e1cb stm32l5 +hw/mcu/st/stm32n6xx_hal_driver https://github.com/STMicroelectronics/stm32n6xx-hal-driver.git 49f9989d10cf6817d4b07ac01848956b46bd0fd6 stm32n6 hw/mcu/st/stm32u5xx_hal_driver https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git 4d93097a67928e9377e655ddd14622adc31b9770 stm32u5 hw/mcu/st/stm32wbxx_hal_driver https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git 2c5f06638be516c1b772f768456ba637f077bac8 stm32wb hw/mcu/ti https://github.com/hathach/ti_driver.git 143ed6cc20a7615d042b03b21e070197d473e6e5 msp430 msp432e4 tm4c diff --git a/examples/build_system/cmake/cpu/cortex-m55.cmake b/examples/build_system/cmake/cpu/cortex-m55.cmake new file mode 100644 index 000000000..a7a57957c --- /dev/null +++ b/examples/build_system/cmake/cpu/cortex-m55.cmake @@ -0,0 +1,26 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -mthumb + -mcpu=cortex-m55 + -mfloat-abi=hard + -mfpu=fpv5-d16 + -mcmse + ) + set(FREERTOS_PORT GCC_ARM_CM55_NTZ_NONSECURE CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "clang") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-m55 + -mfpu=fpv5-d16 + ) + set(FREERTOS_PORT GCC_ARM_CM55_NTZ_NONSECURE CACHE INTERNAL "") + +elseif (TOOLCHAIN STREQUAL "iar") + set(TOOLCHAIN_COMMON_FLAGS + --cpu cortex-m55 + --fpu VFPv5_D16 + ) + set(FREERTOS_PORT IAR_ARM_CM55_NTZ_NONSECURE CACHE INTERNAL "") + +endif () diff --git a/examples/build_system/make/cpu/cortex-m55.mk b/examples/build_system/make/cpu/cortex-m55.mk new file mode 100644 index 000000000..de627caed --- /dev/null +++ b/examples/build_system/make/cpu/cortex-m55.mk @@ -0,0 +1,28 @@ +ifeq ($(TOOLCHAIN),gcc) + CFLAGS += \ + -mthumb \ + -mcpu=cortex-m55 \ + -mfloat-abi=hard \ + -mfpu=fpv5-d16 \ + -mcmse + +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + --target=arm-none-eabi \ + -mcpu=cortex-m55 \ + -mfpu=fpv5-d16 \ + +else ifeq ($(TOOLCHAIN),iar) + CFLAGS += \ + --cpu cortex-m55 \ + --fpu VFPv5_D16 \ + + ASFLAGS += \ + --cpu cortex-m55 \ + --fpu VFPv5_D16 \ + +else + $(error "TOOLCHAIN is not supported") +endif + +FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM55_NTZ/non_secure diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index 5ebe71612..c2e0d54ec 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -10,6 +10,7 @@ mcu:SAMD11 mcu:STM32L0 mcu:STM32F0 mcu:KINETIS_KL +mcu:STM32N6 family:broadcom_64bit family:broadcom_32bit family:espressif diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index 95f9f1d82..9b8d535e6 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -15,3 +15,4 @@ mcu:MAX3421 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32N6 diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index 95f9f1d82..9b8d535e6 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -15,3 +15,4 @@ mcu:MAX3421 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32N6 diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt index e3ae25260..4ff3841a4 100644 --- a/examples/host/cdc_msc_hid_freertos/only.txt +++ b/examples/host/cdc_msc_hid_freertos/only.txt @@ -13,3 +13,4 @@ mcu:MAX3421 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32N6 diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index b6f87f423..6e6e2184f 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -18,3 +18,4 @@ mcu:RAXXX mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32N6 diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt index 95f9f1d82..9b8d535e6 100644 --- a/examples/host/hid_controller/only.txt +++ b/examples/host/hid_controller/only.txt @@ -15,3 +15,4 @@ mcu:MAX3421 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32N6 diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt index b6f87f423..6e6e2184f 100644 --- a/examples/host/midi_rx/only.txt +++ b/examples/host/midi_rx/only.txt @@ -18,3 +18,4 @@ mcu:RAXXX mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32N6 diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index 95f9f1d82..9b8d535e6 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -15,3 +15,4 @@ mcu:MAX3421 mcu:STM32F4 mcu:STM32F7 mcu:STM32H7 +mcu:STM32N6 diff --git a/hw/bsp/stm32n6/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32n6/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..9fd3f6c50 --- /dev/null +++ b/hw/bsp/stm32n6/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,149 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "stm32h7rsxx.h" +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#define configENABLE_FPU 1 +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*8*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 4 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<ROM + + /* The program code and other data into "RAM" Ram type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >ROM + + /* Constant data into "RAM" Ram type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >ROM + + .ARM.extab (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >ROM + + .ARM (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >ROM + + .preinit_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >ROM + + .init_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >ROM + + .fini_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >ROM + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> ROM + + .noncacheable : + { + . = ALIGN(8); + __snoncacheable = .;/* create symbol for start of section */ + KEEP(*(.noncacheable)) + . = ALIGN(8); + __enoncacheable = .; /* create symbol for end of section */ + } > RAM + + + .gnu.sgstubs : + { + . = ALIGN(4); + *(.gnu.sgstubs*) /* Secure Gateway stubs */ + . = ALIGN(4); + } >ROM + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake new file mode 100644 index 000000000..197b5108f --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake @@ -0,0 +1,25 @@ +set(MCU_VARIANT stm32n657xx) +set(JLINK_DEVICE stm32n6xx) + +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/STM32N657XX_LRUN.ld) +set(LD_FILE_Clang ${LD_FILE_GNU}) + +set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) + +function(update_board TARGET) + + target_compile_definitions(${TARGET} PUBLIC + STM32N6xx + SEGGER_RTT_SECTION="noncacheable_buffer" + BUFFER_SIZE_UP=0x3000 + ) + + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tcpp0203/tcpp0203.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tcpp0203/tcpp0203_reg.c + ) + target_include_directories(${TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tcpp0203 + ) +endfunction() diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h new file mode 100644 index 000000000..d3781c6d0 --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.h @@ -0,0 +1,283 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: STM32 H723 Nucleo + url: https://www.st.com/en/evaluation-tools/nucleo-h723zg.html +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stm32n657xx.h" +#include "stm32n6xx_ll_exti.h" +#include "stm32n6xx_ll_system.h" +#include "tcpp0203.h" + +#define UART_DEV USART1 +#define UART_CLK_EN __HAL_RCC_USART1_CLK_ENABLE + +#define BOARD_TUD_RHPORT 1 + +// VBUS Sense detection +#define OTG_FS_VBUS_SENSE 1 +#define OTG_HS_VBUS_SENSE 1 + +#define PINID_LED 0 +#define PINID_BUTTON 1 +#define PINID_UART_TX 2 +#define PINID_UART_RX 3 +#define PINID_TCPP0203_EN 4 + +static board_pindef_t board_pindef[] = { + {// LED + .port = GPIOG, + .pin_init = {.Pin = GPIO_PIN_10, .Mode = GPIO_MODE_OUTPUT_PP, .Pull = GPIO_PULLDOWN, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0}, + .active_state = 1}, + {// Button + .port = GPIOC, + .pin_init = {.Pin = GPIO_PIN_13, .Mode = GPIO_MODE_INPUT, .Pull = GPIO_PULLDOWN, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0}, + .active_state = 1}, + {// UART TX + .port = GPIOE, + .pin_init = {.Pin = GPIO_PIN_5, .Mode = GPIO_MODE_AF_PP, .Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_LOW, .Alternate = GPIO_AF7_USART1}, + .active_state = 0}, + {// UART RX + .port = GPIOE, + .pin_init = {.Pin = GPIO_PIN_6, .Mode = GPIO_MODE_AF_PP, .Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_LOW, .Alternate = GPIO_AF7_USART1}, + .active_state = 0}, + {// VBUS input pin used for TCPP0203 EN + .port = GPIOA, + .pin_init = {.Pin = GPIO_PIN_7, .Mode = GPIO_MODE_OUTPUT_PP, .Pull = GPIO_PULLDOWN, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0}, + .active_state = 0}, + { + // I2C SCL for TCPP0203 + .port = GPIOB, + .pin_init = {.Pin = GPIO_PIN_10, .Mode = GPIO_MODE_AF_OD, .Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_LOW, .Alternate = GPIO_AF4_I2C2}, + }, + { + // I2C SDA for TCPP0203 + .port = GPIOB, + .pin_init = {.Pin = GPIO_PIN_11, .Mode = GPIO_MODE_AF_OD, .Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_LOW, .Alternate = GPIO_AF4_I2C2}, + }, + { + // INT for TCPP0203 + .port = GPIOD, + .pin_init = {.Pin = GPIO_PIN_2, .Mode = GPIO_MODE_IT_FALLING, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0}, + }, +}; + +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ +void SystemClock_Config(void) { + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + /* Configure the power domain */ + if (HAL_PWREx_ConfigSupply(PWR_EXTERNAL_SOURCE_SUPPLY) != HAL_OK) { + Error_Handler(); + } + + /* Get current CPU/System buses clocks configuration */ + /* and if necessary switch to intermediate HSI clock */ + /* to ensure target clock can be set */ + HAL_RCC_GetClockConfig(&RCC_ClkInitStruct); + if ((RCC_ClkInitStruct.CPUCLKSource == RCC_CPUCLKSOURCE_IC1) || + (RCC_ClkInitStruct.SYSCLKSource == RCC_SYSCLKSOURCE_IC2_IC6_IC11)) { + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_CPUCLK | RCC_CLOCKTYPE_SYSCLK); + RCC_ClkInitStruct.CPUCLKSource = RCC_CPUCLKSOURCE_HSI; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct) != HAL_OK) { + Error_Handler(); + } + } + + /* HSE selected as source (stable clock on Level 0 samples */ + /* PLL1 output = ((HSE/PLLM)*PLLN)/PLLP1/PLLP2 */ + /* = ((48000000/3)*75)/1/1 */ + /* = (16000000*75)/1/1 */ + /* = 1200000000 (1200 MHz) */ + /* PLL2 off */ + /* PLL3 off */ + /* PLL4 off */ + + /* Enable HSE && HSI */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSIState = RCC_HSI_OFF; + RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; /* 48 MHz */ + + RCC_OscInitStruct.PLL1.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL1.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL1.PLLM = 3; + RCC_OscInitStruct.PLL1.PLLN = 75; /* PLL1 VCO = 48/3 * 75 = 1200MHz */ + RCC_OscInitStruct.PLL1.PLLP1 = 1; /* PLL output = PLL VCO frequency / (PLLP1 * PLLP2) */ + RCC_OscInitStruct.PLL1.PLLP2 = 1; /* PLL output = 1200 MHz */ + RCC_OscInitStruct.PLL1.PLLFractional = 0; + + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + /* Initialization error */ + Error_Handler(); + } + + /* Select PLL1 outputs as CPU and System bus clock source */ + /* CPUCLK = ic1_ck = PLL1 output/ic1_divider = 600 MHz */ + /* SYSCLK = ic2_ck = PLL1 output/ic2_divider = 400 MHz */ + /* Configure the HCLK clock divider */ + /* HCLK = PLL1 SYSCLK/HCLK divider = 200 MHz */ + /* PCLKx = HCLK / PCLKx divider = 200 MHz */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_CPUCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | + RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK4 | RCC_CLOCKTYPE_PCLK5); + RCC_ClkInitStruct.CPUCLKSource = RCC_CPUCLKSOURCE_IC1; + RCC_ClkInitStruct.IC1Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1; + RCC_ClkInitStruct.IC1Selection.ClockDivider = 2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_IC2_IC6_IC11; + RCC_ClkInitStruct.IC2Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1; + RCC_ClkInitStruct.IC2Selection.ClockDivider = 3; + RCC_ClkInitStruct.IC6Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1; + RCC_ClkInitStruct.IC6Selection.ClockDivider = 3; + RCC_ClkInitStruct.IC11Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1; + RCC_ClkInitStruct.IC11Selection.ClockDivider = 3; + RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV1; + RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV1; + RCC_ClkInitStruct.APB5CLKDivider = RCC_APB5_DIV1; + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct) != HAL_OK) { + /* Initialization Error */ + Error_Handler(); + } + + /** Initializes the peripherals clock + */ + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USBOTGHS1; + PeriphClkInitStruct.UsbOtgHs1ClockSelection = RCC_USBPHY1REFCLKSOURCE_HSE_DIRECT; + + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + /* Initialization Error */ + Error_Handler(); + } + + /** Set USB OTG HS PHY1 Reference Clock Source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USBPHY1; + PeriphClkInitStruct.UsbPhy1ClockSelection = RCC_USBPHY1REFCLKSOURCE_HSE_DIRECT; + + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + /* Initialization Error */ + Error_Handler(); + } +} + +//--------------------------------------------------------------------+ +// USB PD +//--------------------------------------------------------------------+ +static I2C_HandleTypeDef i2c_handle = { + .Instance = I2C2, + .Init = { + .Timing = 0x20C0EDFF, + .OwnAddress1 = 0, + .AddressingMode = I2C_ADDRESSINGMODE_7BIT, + .DualAddressMode = I2C_DUALADDRESS_DISABLE, + .OwnAddress2 = 0, + .OwnAddress2Masks = I2C_OA2_NOMASK, + .GeneralCallMode = I2C_GENERALCALL_DISABLE, + .NoStretchMode = I2C_NOSTRETCH_DISABLE, + }}; +static TCPP0203_Object_t tcpp0203_obj = {0}; + +int32_t board_tcpp0203_init(void) { + board_pindef_t *pindef = &board_pindef[PINID_TCPP0203_EN]; + HAL_GPIO_WritePin(pindef->port, pindef->pin_init.Pin, GPIO_PIN_SET); + + __HAL_RCC_I2C2_CLK_ENABLE(); + __HAL_RCC_I2C2_FORCE_RESET(); + __HAL_RCC_I2C2_RELEASE_RESET(); + if (HAL_I2C_Init(&i2c_handle) != HAL_OK) { + return HAL_ERROR; + } + + NVIC_SetPriority(EXTI8_IRQn, 12); + NVIC_EnableIRQ(EXTI8_IRQn); + + return 0; +} + +int32_t board_tcpp0203_deinit(void) { + return 0; +} + +int32_t i2c_readreg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { + TU_ASSERT(HAL_OK == HAL_I2C_Mem_Read(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000)); + return 0; +} + +int32_t i2c_writereg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { + TU_ASSERT(HAL_OK == HAL_I2C_Mem_Write(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000)); + return 0; +} + +static inline void board_init2(void) { + TCPP0203_IO_t io_ctx; + + io_ctx.Address = TCPP0203_I2C_ADDRESS_X68; + io_ctx.Init = board_tcpp0203_init; + io_ctx.DeInit = board_tcpp0203_deinit; + io_ctx.ReadReg = i2c_readreg; + io_ctx.WriteReg = i2c_writereg; + + TU_ASSERT(TCPP0203_RegisterBusIO(&tcpp0203_obj, &io_ctx) == TCPP0203_OK, ); + + TU_ASSERT(TCPP0203_Init(&tcpp0203_obj) == TCPP0203_OK, ); + + TU_ASSERT(TCPP0203_SetPowerMode(&tcpp0203_obj, TCPP0203_POWER_MODE_NORMAL) == TCPP0203_OK, ); +} + +void board_vbus_set(uint8_t rhport, bool state) { + (void) state; + if (rhport == 1) { + TU_ASSERT(TCPP0203_SetGateDriverProvider(&tcpp0203_obj, TCPP0203_GD_PROVIDER_SWITCH_CLOSED) == TCPP0203_OK, ); + } +} + +void EXTI8_IRQHandler(void) { + __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_8); + if (tcpp0203_obj.IsInitialized) { + TU_ASSERT(TCPP0203_SetPowerMode(&tcpp0203_obj, TCPP0203_POWER_MODE_NORMAL) == TCPP0203_OK, ); + TU_ASSERT(TCPP0203_SetGateDriverProvider(&tcpp0203_obj, TCPP0203_GD_PROVIDER_SWITCH_CLOSED) == TCPP0203_OK, ); + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk new file mode 100644 index 000000000..b851da0ca --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk @@ -0,0 +1,23 @@ +MCU_VARIANT = stm32n6xx +CFLAGS += -DSTM32N6xx + +# For flash-jlink target +JLINK_DEVICE = stm32n6xx + +# flash target using on-board stlink +flash: flash-stlink + +PORT = 1 + + +SRC_C += \ + $(BOARD_PATH)/tcpp0203/tcpp0203.c \ + $(BOARD_PATH)/tcpp0203/tcpp0203_reg.c \ + +INC += \ + $(TOP)/$(BOARD_PATH)/tcpp0203 \ + +CFLAGS += \ + -DSEGGER_RTT_SECTION=\"noncacheable_buffer\" \ + -DSTM32N657xx + -DBUFFER_SIZE_UP=0x3000 \ diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/LICENSE.txt b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/LICENSE.txt new file mode 100644 index 000000000..1cbbc544a --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/LICENSE.txt @@ -0,0 +1,6 @@ +This software component is provided to you as part of a software package and +applicable license terms are in the Package_license file. If you received this +software component outside of a package or without applicable license terms, +the terms of the BSD-3-Clause license shall apply. +You may obtain a copy of the BSD-3-Clause at: +https://opensource.org/licenses/BSD-3-Clause diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/Release_Notes.html b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/Release_Notes.html new file mode 100644 index 000000000..6bbba86a4 --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/Release_Notes.html @@ -0,0 +1,205 @@ + + + + + + + Release Notes for TCPP0203 Component Driver + + + + + + +
+
+
+

Release Notes for TCPP0203 Component Driver

+

Copyright © 2020 STMicroelectronics
+

+ +
+

Purpose

+

This driver provides a set of functions needed to drive TCPP0203 Type-C Port Protection component

+
+
+

Update History

+
+ +
+

Main Changes

+

Maintenance release

+

Contents

+ + + + + + + + + + + +
Headline
MISRA Rule-81.13 correction on TCPP0203 component driver files
+

Backward compatibility

+

No compatibility break with previous version

+

Dependencies

+
+
+
+ +
+

Main Changes

+

Maintenance release

+

Contents

+ + + + + + + + + + + + +
Fixed bugs list
Headline
MISRA corrections on TCPP0203 component driver files
+

Known Limitations

+

Outstanding bugs list : None

+

Requirements not met or planned in a forthcoming release : None

+

Development Toolchains and Compilers

+
    +
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • +
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • +
  • STM32CubeIDE toolchain V1.8.0
  • +
+

Backward compatibility

+

No compatibility break with previous version

+

Dependencies

+
+
+
+ +
+

Main Changes

+

Maintenance release

+

Contents

+ + + + + + + + + + + + +
Fixed bugs list
Headline
License updates
+

Known Limitations

+

Outstanding bugs list : None

+

Requirements not met or planned in a forthcoming release : None

+

Development Toolchains and Compilers

+
    +
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • +
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • +
  • STM32CubeIDE toolchain V1.6.0
  • +
+

Backward compatibility

+

No compatibility break with previous version

+

Dependencies

+
+
+
+ +
+

Main Changes

+

Maintenance release

+

Contents

+ + + + + + + + + + + + +
Fixed bugs list
Headline
CodeSpell correction on TCPP0203 component driver files
+

Known Limitations

+

Outstanding bugs list : None

+

Requirements not met or planned in a forthcoming release : None

+

Development Toolchains and Compilers

+
    +
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • +
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • +
  • STM32CubeIDE toolchain V1.5.0
  • +
+

Backward compatibility

+

No compatibility break with previous version

+

Dependencies

+
+
+
+ +
+

Main Changes

+

Maintenance release

+

Contents

+ + + + + + + + + + + + +
Fixed bugs list
Headline
MCUAstyle correction on TCPP0203 component driver files
+

Known Limitations

+

Outstanding bugs list : None

+

Requirements not met or planned in a forthcoming release : None

+

Development Toolchains and Compilers

+
    +
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • +
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • +
  • STM32CubeIDE toolchain V1.5.0
  • +
+

Backward compatibility

+

No compatibility break with previous version

+

Dependencies

+
+
+
+ +
+

Main Changes

+
    +
  • First official release of TCPP0203 Type-C port Protection Component drivers
  • +
+
+
+
+
+
+

For complete documentation on STM32,visit: [www.st.com/stm32]

+This release note uses up to date web standards and, for this reason, should not be opened with Internet Explorer but preferably with popular browsers such as Google Chrome, Mozilla Firefox, Opera or Microsoft Edge. +
+ + diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/favicon.png b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..06713eec4974e141c6e9b4156d34e61e89f282ca GIT binary patch literal 4126 zcmV+(5aI8MP)ZIGU@QfPy~$kHP}Vz9c$a)g>fT6hB^OaK4>c|MGS0000HbW%=J|NsC0|NsC0 z|NsC0|NsC0041%NVgLXD!bwCyRCwCllie1CAP9sJ&9ooo{hxLjw5@YC+xxf~%TE}{ zNd5%935b--eKa7{Q8)vZ;eI6pGFH>rL)887WOA={e(b_&0g-g6to#Hm2B3vqWV>1u z@z7*I(bdWdx-Y=OT@|og)oZEgAbc7ep|Gf{$7j1Oa#T&r4>0xv(+}tR_4biWa z1Q-BfcsgeLIJPbT0000rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000F^NklQWRUVq~pvFslpiNq83Yr*1(ELa!!kppKfxQKEkPzz^I>0W)!71xam z(B64`)5a~kHf9SBOp*Wvo{xA*e4|Kv3g6TCo+fF8q^C$|g>#NlXyY$%lmkmCh$x1Z zFbJ_hiDG`37w>KPVB83d7E3>R@-M9$`|}|QFF}1qSk!nanPdVd3K38edo3y+D*=Uo zfOWCwj(F@GSjPG&B<0O;H!Zm0g>eDeK09{b@xB};mEy; z;Gp5H_Cr65qKM1uYIu6x&16!Ei=BHfJLe)1IUnFqc6d#D=ZVQmV9C73vy1=x$SK;s z=*CYZP+Ei1D5Vjl#u88v5dv#jId?iu)8mM}{mD`GcMXtAC5ap?ZoKr&iYuqTKHe$t zTR%R$ZZwxec?l+0r_LIVbe-mzH+D0*ZYsu4BE~~JA2A+AD?BAArO=g8ZfvXtU~o9c zZ(Bd-RFK5jh*DvM1v6^41HB@0K0qn7E8E&Xz1mk6hvmx?*|WB_H!dcO;5R$=<4b~s z5zr3N4zxlkMKOrDeny(PGpEM6^hGyc7lhg>MWtM!af*pn%&q_PxI(n^(-Zd{ICPAp z(WE@Zz5|EZyt{MEDy&l5$Cba^zU!9k&;Vs7lk$@o02LOwb#e2{#3%Cn2>kQF(RKUU z+tW!;FT0@d+TX^L;>@3RytlTP&ts$pqA}TwENBlg9?$-D zF9Sn4URZx8)hVBw<~NY=h3=so7{jEhG%Zc_0QBSvY~K4BS|W5MAem5XSb6m}VDN$f zy+b3n9qjIJoHM5pqYa`IPH9AIoM=!AE1Er>r|3E}#Jq-S)cTrfD&TZjAuN@+V}3mi zlhOce+q<8>Y?i93G=*Z3Web`ri!Q%p%LR*(bB?;|)B`&=J&ab0Z(UKpbzyZV5o*#& z0FLzzaI$v*-#WB)+`n>BoJ*1AwU0XSu;@w&Hu1WYXVR#!8itC%68CzMeiXhL#`9W$9J30NB-Wg!ex`hBlg9F5u@&o4>hd`TWPv z{r{JbyvQGZzbyvPS}zAifbhF49z~X|@9v|!=No>qsF|P~vf=g>7#%0yk<U?Ha8*Z4HW>#8w>z$A3 z>^uQlk;$a-6CQ(uc@RM)Cbss!xuPVl2@c1u-5tEUw}U8OfP_J+QYhfu$B<0Cj3xm7 c?*aZZ00ulYFs-m=@&Et;07*qoM6N<$f~=14i~s-t literal 0 HcmV?d00001 diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/mini-st_2020.css b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/mini-st_2020.css new file mode 100644 index 000000000..dd19969d1 --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/mini-st_2020.css @@ -0,0 +1,1703 @@ +@charset "UTF-8"; +/* + Flavor name: Custom (mini-custom) + Generated online - https://minicss.org/flavors + mini.css version: v3.0.1 +*/ +/* + Browsers resets and base typography. +*/ +/* Core module CSS variable definitions */ +:root { + --fore-color: #03234b; + --secondary-fore-color: #03234b; + --back-color: #ffffff; + --secondary-back-color: #ffffff; + --blockquote-color: #e6007e; + --pre-color: #e6007e; + --border-color: #3cb4e6; + --secondary-border-color: #3cb4e6; + --heading-ratio: 1.2; + --universal-margin: 0.5rem; + --universal-padding: 0.25rem; + --universal-border-radius: 0.075rem; + --background-margin: 1.5%; + --a-link-color: #3cb4e6; + --a-visited-color: #8c0078; } + +html { + font-size: 13.5px; } + +a, b, del, em, i, ins, q, span, strong, u { + font-size: 1em; } + +html, * { + font-family: -apple-system, BlinkMacSystemFont, Helvetica, arial, sans-serif; + line-height: 1.25; + -webkit-text-size-adjust: 100%; } + +* { + font-size: 1rem; } + +body { + margin: 0; + color: var(--fore-color); + @background: var(--back-color); + background: var(--back-color) linear-gradient(#ffd200, #ffd200) repeat-y left top; + background-size: var(--background-margin); + } + +details { + display: block; } + +summary { + display: list-item; } + +abbr[title] { + border-bottom: none; + text-decoration: underline dotted; } + +input { + overflow: visible; } + +img { + max-width: 100%; + height: auto; } + +h1, h2, h3, h4, h5, h6 { + line-height: 1.25; + margin: calc(1.5 * var(--universal-margin)) var(--universal-margin); + font-weight: 400; } + h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { + color: var(--secondary-fore-color); + display: block; + margin-top: -0.25rem; } + +h1 { + font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio)); } + +h2 { + font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) ); + border-style: none none solid none ; + border-width: thin; + border-color: var(--border-color); } +h3 { + font-size: calc(1rem * var(--heading-ratio) ); } + +h4 { + font-size: calc(1rem * var(--heading-ratio)); } + +h5 { + font-size: 1rem; } + +h6 { + font-size: calc(1rem / var(--heading-ratio)); } + +p { + margin: var(--universal-margin); } + +ol, ul { + margin: var(--universal-margin); + padding-left: calc(3 * var(--universal-margin)); } + +b, strong { + font-weight: 700; } + +hr { + box-sizing: content-box; + border: 0; + line-height: 1.25em; + margin: var(--universal-margin); + height: 0.0714285714rem; + background: linear-gradient(to right, transparent, var(--border-color) 20%, var(--border-color) 80%, transparent); } + +blockquote { + display: block; + position: relative; + font-style: italic; + color: var(--secondary-fore-color); + margin: var(--universal-margin); + padding: calc(3 * var(--universal-padding)); + border: 0.0714285714rem solid var(--secondary-border-color); + border-left: 0.3rem solid var(--blockquote-color); + border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } + blockquote:before { + position: absolute; + top: calc(0rem - var(--universal-padding)); + left: 0; + font-family: sans-serif; + font-size: 2rem; + font-weight: 800; + content: "\201c"; + color: var(--blockquote-color); } + blockquote[cite]:after { + font-style: normal; + font-size: 0.75em; + font-weight: 700; + content: "\a— " attr(cite); + white-space: pre; } + +code, kbd, pre, samp { + font-family: Menlo, Consolas, monospace; + font-size: 0.85em; } + +code { + background: var(--secondary-back-color); + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } + +kbd { + background: var(--fore-color); + color: var(--back-color); + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } + +pre { + overflow: auto; + background: var(--secondary-back-color); + padding: calc(1.5 * var(--universal-padding)); + margin: var(--universal-margin); + border: 0.0714285714rem solid var(--secondary-border-color); + border-left: 0.2857142857rem solid var(--pre-color); + border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } + +sup, sub, code, kbd { + line-height: 0; + position: relative; + vertical-align: baseline; } + +small, sup, sub, figcaption { + font-size: 0.75em; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +figure { + margin: var(--universal-margin); } + +figcaption { + color: var(--secondary-fore-color); } + +a { + text-decoration: none; } + a:link { + color: var(--a-link-color); } + a:visited { + color: var(--a-visited-color); } + a:hover, a:focus { + text-decoration: underline; } + +/* + Definitions for the grid system, cards and containers. +*/ +.container { + margin: 0 auto; + padding: 0 calc(1.5 * var(--universal-padding)); } + +.row { + box-sizing: border-box; + display: flex; + flex: 0 1 auto; + flex-flow: row wrap; + margin: 0 0 0 var(--background-margin); } + +.col-sm, +[class^='col-sm-'], +[class^='col-sm-offset-'], +.row[class*='cols-sm-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + +.col-sm, +.row.cols-sm > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + +.col-sm-1, +.row.cols-sm-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + +.col-sm-offset-0 { + margin-left: 0; } + +.col-sm-2, +.row.cols-sm-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + +.col-sm-offset-1 { + margin-left: 8.3333333333%; } + +.col-sm-3, +.row.cols-sm-3 > * { + max-width: 25%; + flex-basis: 25%; } + +.col-sm-offset-2 { + margin-left: 16.6666666667%; } + +.col-sm-4, +.row.cols-sm-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + +.col-sm-offset-3 { + margin-left: 25%; } + +.col-sm-5, +.row.cols-sm-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + +.col-sm-offset-4 { + margin-left: 33.3333333333%; } + +.col-sm-6, +.row.cols-sm-6 > * { + max-width: 50%; + flex-basis: 50%; } + +.col-sm-offset-5 { + margin-left: 41.6666666667%; } + +.col-sm-7, +.row.cols-sm-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + +.col-sm-offset-6 { + margin-left: 50%; } + +.col-sm-8, +.row.cols-sm-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + +.col-sm-offset-7 { + margin-left: 58.3333333333%; } + +.col-sm-9, +.row.cols-sm-9 > * { + max-width: 75%; + flex-basis: 75%; } + +.col-sm-offset-8 { + margin-left: 66.6666666667%; } + +.col-sm-10, +.row.cols-sm-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + +.col-sm-offset-9 { + margin-left: 75%; } + +.col-sm-11, +.row.cols-sm-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + +.col-sm-offset-10 { + margin-left: 83.3333333333%; } + +.col-sm-12, +.row.cols-sm-12 > * { + max-width: 100%; + flex-basis: 100%; } + +.col-sm-offset-11 { + margin-left: 91.6666666667%; } + +.col-sm-normal { + order: initial; } + +.col-sm-first { + order: -999; } + +.col-sm-last { + order: 999; } + +@media screen and (min-width: 500px) { + .col-md, + [class^='col-md-'], + [class^='col-md-offset-'], + .row[class*='cols-md-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + + .col-md, + .row.cols-md > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + + .col-md-1, + .row.cols-md-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + + .col-md-offset-0 { + margin-left: 0; } + + .col-md-2, + .row.cols-md-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + + .col-md-offset-1 { + margin-left: 8.3333333333%; } + + .col-md-3, + .row.cols-md-3 > * { + max-width: 25%; + flex-basis: 25%; } + + .col-md-offset-2 { + margin-left: 16.6666666667%; } + + .col-md-4, + .row.cols-md-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + + .col-md-offset-3 { + margin-left: 25%; } + + .col-md-5, + .row.cols-md-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + + .col-md-offset-4 { + margin-left: 33.3333333333%; } + + .col-md-6, + .row.cols-md-6 > * { + max-width: 50%; + flex-basis: 50%; } + + .col-md-offset-5 { + margin-left: 41.6666666667%; } + + .col-md-7, + .row.cols-md-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + + .col-md-offset-6 { + margin-left: 50%; } + + .col-md-8, + .row.cols-md-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + + .col-md-offset-7 { + margin-left: 58.3333333333%; } + + .col-md-9, + .row.cols-md-9 > * { + max-width: 75%; + flex-basis: 75%; } + + .col-md-offset-8 { + margin-left: 66.6666666667%; } + + .col-md-10, + .row.cols-md-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + + .col-md-offset-9 { + margin-left: 75%; } + + .col-md-11, + .row.cols-md-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + + .col-md-offset-10 { + margin-left: 83.3333333333%; } + + .col-md-12, + .row.cols-md-12 > * { + max-width: 100%; + flex-basis: 100%; } + + .col-md-offset-11 { + margin-left: 91.6666666667%; } + + .col-md-normal { + order: initial; } + + .col-md-first { + order: -999; } + + .col-md-last { + order: 999; } } +@media screen and (min-width: 1280px) { + .col-lg, + [class^='col-lg-'], + [class^='col-lg-offset-'], + .row[class*='cols-lg-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + + .col-lg, + .row.cols-lg > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + + .col-lg-1, + .row.cols-lg-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + + .col-lg-offset-0 { + margin-left: 0; } + + .col-lg-2, + .row.cols-lg-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + + .col-lg-offset-1 { + margin-left: 8.3333333333%; } + + .col-lg-3, + .row.cols-lg-3 > * { + max-width: 25%; + flex-basis: 25%; } + + .col-lg-offset-2 { + margin-left: 16.6666666667%; } + + .col-lg-4, + .row.cols-lg-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + + .col-lg-offset-3 { + margin-left: 25%; } + + .col-lg-5, + .row.cols-lg-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + + .col-lg-offset-4 { + margin-left: 33.3333333333%; } + + .col-lg-6, + .row.cols-lg-6 > * { + max-width: 50%; + flex-basis: 50%; } + + .col-lg-offset-5 { + margin-left: 41.6666666667%; } + + .col-lg-7, + .row.cols-lg-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + + .col-lg-offset-6 { + margin-left: 50%; } + + .col-lg-8, + .row.cols-lg-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + + .col-lg-offset-7 { + margin-left: 58.3333333333%; } + + .col-lg-9, + .row.cols-lg-9 > * { + max-width: 75%; + flex-basis: 75%; } + + .col-lg-offset-8 { + margin-left: 66.6666666667%; } + + .col-lg-10, + .row.cols-lg-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + + .col-lg-offset-9 { + margin-left: 75%; } + + .col-lg-11, + .row.cols-lg-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + + .col-lg-offset-10 { + margin-left: 83.3333333333%; } + + .col-lg-12, + .row.cols-lg-12 > * { + max-width: 100%; + flex-basis: 100%; } + + .col-lg-offset-11 { + margin-left: 91.6666666667%; } + + .col-lg-normal { + order: initial; } + + .col-lg-first { + order: -999; } + + .col-lg-last { + order: 999; } } +/* Card component CSS variable definitions */ +:root { + --card-back-color: #3cb4e6; + --card-fore-color: #03234b; + --card-border-color: #03234b; } + +.card { + display: flex; + flex-direction: column; + justify-content: space-between; + align-self: center; + position: relative; + width: 100%; + background: var(--card-back-color); + color: var(--card-fore-color); + border: 0.0714285714rem solid var(--card-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); + overflow: hidden; } + @media screen and (min-width: 320px) { + .card { + max-width: 320px; } } + .card > .sectione { + background: var(--card-back-color); + color: var(--card-fore-color); + box-sizing: border-box; + margin: 0; + border: 0; + border-radius: 0; + border-bottom: 0.0714285714rem solid var(--card-border-color); + padding: var(--universal-padding); + width: 100%; } + .card > .sectione.media { + height: 200px; + padding: 0; + -o-object-fit: cover; + object-fit: cover; } + .card > .sectione:last-child { + border-bottom: 0; } + +/* + Custom elements for card elements. +*/ +@media screen and (min-width: 240px) { + .card.small { + max-width: 240px; } } +@media screen and (min-width: 480px) { + .card.large { + max-width: 480px; } } +.card.fluid { + max-width: 100%; + width: auto; } + +.card.warning { + --card-back-color: #e5b8b7; + --card-fore-color: #3b234b; + --card-border-color: #8c0078; } + +.card.error { + --card-back-color: #464650; + --card-fore-color: #ffffff; + --card-border-color: #8c0078; } + +.card > .sectione.dark { + --card-back-color: #3b234b; + --card-fore-color: #ffffff; } + +.card > .sectione.double-padded { + padding: calc(1.5 * var(--universal-padding)); } + +/* + Definitions for forms and input elements. +*/ +/* Input_control module CSS variable definitions */ +:root { + --form-back-color: #ffe97f; + --form-fore-color: #03234b; + --form-border-color: #3cb4e6; + --input-back-color: #ffffff; + --input-fore-color: #03234b; + --input-border-color: #3cb4e6; + --input-focus-color: #0288d1; + --input-invalid-color: #d32f2f; + --button-back-color: #e2e2e2; + --button-hover-back-color: #dcdcdc; + --button-fore-color: #212121; + --button-border-color: transparent; + --button-hover-border-color: transparent; + --button-group-border-color: rgba(124, 124, 124, 0.54); } + +form { + background: var(--form-back-color); + color: var(--form-fore-color); + border: 0.0714285714rem solid var(--form-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); + padding: calc(2 * var(--universal-padding)) var(--universal-padding); } + +fieldset { + border: 0.0714285714rem solid var(--form-border-color); + border-radius: var(--universal-border-radius); + margin: calc(var(--universal-margin) / 4); + padding: var(--universal-padding); } + +legend { + box-sizing: border-box; + display: table; + max-width: 100%; + white-space: normal; + font-weight: 500; + padding: calc(var(--universal-padding) / 2); } + +label { + padding: calc(var(--universal-padding) / 2) var(--universal-padding); } + +.input-group { + display: inline-block; } + .input-group.fluid { + display: flex; + align-items: center; + justify-content: center; } + .input-group.fluid > input { + max-width: 100%; + flex-grow: 1; + flex-basis: 0px; } + @media screen and (max-width: 499px) { + .input-group.fluid { + align-items: stretch; + flex-direction: column; } } + .input-group.vertical { + display: flex; + align-items: stretch; + flex-direction: column; } + .input-group.vertical > input { + max-width: 100%; + flex-grow: 1; + flex-basis: 0px; } + +[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { + height: auto; } + +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; } + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +input:not([type]), [type="text"], [type="email"], [type="number"], [type="search"], +[type="password"], [type="url"], [type="tel"], [type="checkbox"], [type="radio"], textarea, select { + box-sizing: border-box; + background: var(--input-back-color); + color: var(--input-fore-color); + border: 0.0714285714rem solid var(--input-border-color); + border-radius: var(--universal-border-radius); + margin: calc(var(--universal-margin) / 2); + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } + +input:not([type="button"]):not([type="submit"]):not([type="reset"]):hover, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus, textarea:hover, textarea:focus, select:hover, select:focus { + border-color: var(--input-focus-color); + box-shadow: none; } +input:not([type="button"]):not([type="submit"]):not([type="reset"]):invalid, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus:invalid, textarea:invalid, textarea:focus:invalid, select:invalid, select:focus:invalid { + border-color: var(--input-invalid-color); + box-shadow: none; } +input:not([type="button"]):not([type="submit"]):not([type="reset"])[readonly], textarea[readonly], select[readonly] { + background: var(--secondary-back-color); } + +select { + max-width: 100%; } + +option { + overflow: hidden; + text-overflow: ellipsis; } + +[type="checkbox"], [type="radio"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + position: relative; + height: calc(1rem + var(--universal-padding) / 2); + width: calc(1rem + var(--universal-padding) / 2); + vertical-align: text-bottom; + padding: 0; + flex-basis: calc(1rem + var(--universal-padding) / 2) !important; + flex-grow: 0 !important; } + [type="checkbox"]:checked:before, [type="radio"]:checked:before { + position: absolute; } + +[type="checkbox"]:checked:before { + content: '\2713'; + font-family: sans-serif; + font-size: calc(1rem + var(--universal-padding) / 2); + top: calc(0rem - var(--universal-padding)); + left: calc(var(--universal-padding) / 4); } + +[type="radio"] { + border-radius: 100%; } + [type="radio"]:checked:before { + border-radius: 100%; + content: ''; + top: calc(0.0714285714rem + var(--universal-padding) / 2); + left: calc(0.0714285714rem + var(--universal-padding) / 2); + background: var(--input-fore-color); + width: 0.5rem; + height: 0.5rem; } + +:placeholder-shown { + color: var(--input-fore-color); } + +::-ms-placeholder { + color: var(--input-fore-color); + opacity: 0.54; } + +button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; } + +button, html [type="button"], [type="reset"], [type="submit"] { + -webkit-appearance: button; } + +button { + overflow: visible; + text-transform: none; } + +button, [type="button"], [type="submit"], [type="reset"], +a.button, label.button, .button, +a[role="button"], label[role="button"], [role="button"] { + display: inline-block; + background: var(--button-back-color); + color: var(--button-fore-color); + border: 0.0714285714rem solid var(--button-border-color); + border-radius: var(--universal-border-radius); + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); + margin: var(--universal-margin); + text-decoration: none; + cursor: pointer; + transition: background 0.3s; } + button:hover, button:focus, [type="button"]:hover, [type="button"]:focus, [type="submit"]:hover, [type="submit"]:focus, [type="reset"]:hover, [type="reset"]:focus, + a.button:hover, + a.button:focus, label.button:hover, label.button:focus, .button:hover, .button:focus, + a[role="button"]:hover, + a[role="button"]:focus, label[role="button"]:hover, label[role="button"]:focus, [role="button"]:hover, [role="button"]:focus { + background: var(--button-hover-back-color); + border-color: var(--button-hover-border-color); } + +input:disabled, input[disabled], textarea:disabled, textarea[disabled], select:disabled, select[disabled], button:disabled, button[disabled], .button:disabled, .button[disabled], [role="button"]:disabled, [role="button"][disabled] { + cursor: not-allowed; + opacity: 0.75; } + +.button-group { + display: flex; + border: 0.0714285714rem solid var(--button-group-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); } + .button-group > button, .button-group [type="button"], .button-group > [type="submit"], .button-group > [type="reset"], .button-group > .button, .button-group > [role="button"] { + margin: 0; + max-width: 100%; + flex: 1 1 auto; + text-align: center; + border: 0; + border-radius: 0; + box-shadow: none; } + .button-group > :not(:first-child) { + border-left: 0.0714285714rem solid var(--button-group-border-color); } + @media screen and (max-width: 499px) { + .button-group { + flex-direction: column; } + .button-group > :not(:first-child) { + border: 0; + border-top: 0.0714285714rem solid var(--button-group-border-color); } } + +/* + Custom elements for forms and input elements. +*/ +button.primary, [type="button"].primary, [type="submit"].primary, [type="reset"].primary, .button.primary, [role="button"].primary { + --button-back-color: #1976d2; + --button-fore-color: #f8f8f8; } + button.primary:hover, button.primary:focus, [type="button"].primary:hover, [type="button"].primary:focus, [type="submit"].primary:hover, [type="submit"].primary:focus, [type="reset"].primary:hover, [type="reset"].primary:focus, .button.primary:hover, .button.primary:focus, [role="button"].primary:hover, [role="button"].primary:focus { + --button-hover-back-color: #1565c0; } + +button.secondary, [type="button"].secondary, [type="submit"].secondary, [type="reset"].secondary, .button.secondary, [role="button"].secondary { + --button-back-color: #d32f2f; + --button-fore-color: #f8f8f8; } + button.secondary:hover, button.secondary:focus, [type="button"].secondary:hover, [type="button"].secondary:focus, [type="submit"].secondary:hover, [type="submit"].secondary:focus, [type="reset"].secondary:hover, [type="reset"].secondary:focus, .button.secondary:hover, .button.secondary:focus, [role="button"].secondary:hover, [role="button"].secondary:focus { + --button-hover-back-color: #c62828; } + +button.tertiary, [type="button"].tertiary, [type="submit"].tertiary, [type="reset"].tertiary, .button.tertiary, [role="button"].tertiary { + --button-back-color: #308732; + --button-fore-color: #f8f8f8; } + button.tertiary:hover, button.tertiary:focus, [type="button"].tertiary:hover, [type="button"].tertiary:focus, [type="submit"].tertiary:hover, [type="submit"].tertiary:focus, [type="reset"].tertiary:hover, [type="reset"].tertiary:focus, .button.tertiary:hover, .button.tertiary:focus, [role="button"].tertiary:hover, [role="button"].tertiary:focus { + --button-hover-back-color: #277529; } + +button.inverse, [type="button"].inverse, [type="submit"].inverse, [type="reset"].inverse, .button.inverse, [role="button"].inverse { + --button-back-color: #212121; + --button-fore-color: #f8f8f8; } + button.inverse:hover, button.inverse:focus, [type="button"].inverse:hover, [type="button"].inverse:focus, [type="submit"].inverse:hover, [type="submit"].inverse:focus, [type="reset"].inverse:hover, [type="reset"].inverse:focus, .button.inverse:hover, .button.inverse:focus, [role="button"].inverse:hover, [role="button"].inverse:focus { + --button-hover-back-color: #111; } + +button.small, [type="button"].small, [type="submit"].small, [type="reset"].small, .button.small, [role="button"].small { + padding: calc(0.5 * var(--universal-padding)) calc(0.75 * var(--universal-padding)); + margin: var(--universal-margin); } + +button.large, [type="button"].large, [type="submit"].large, [type="reset"].large, .button.large, [role="button"].large { + padding: calc(1.5 * var(--universal-padding)) calc(2 * var(--universal-padding)); + margin: var(--universal-margin); } + +/* + Definitions for navigation elements. +*/ +/* Navigation module CSS variable definitions */ +:root { + --header-back-color: #03234b; + --header-hover-back-color: #ffd200; + --header-fore-color: #ffffff; + --header-border-color: #3cb4e6; + --nav-back-color: #ffffff; + --nav-hover-back-color: #ffe97f; + --nav-fore-color: #e6007e; + --nav-border-color: #3cb4e6; + --nav-link-color: #3cb4e6; + --footer-fore-color: #ffffff; + --footer-back-color: #03234b; + --footer-border-color: #3cb4e6; + --footer-link-color: #3cb4e6; + --drawer-back-color: #ffffff; + --drawer-hover-back-color: #ffe97f; + --drawer-border-color: #3cb4e6; + --drawer-close-color: #e6007e; } + +header { + height: 2.75rem; + background: var(--header-back-color); + color: var(--header-fore-color); + border-bottom: 0.0714285714rem solid var(--header-border-color); + padding: calc(var(--universal-padding) / 4) 0; + white-space: nowrap; + overflow-x: auto; + overflow-y: hidden; } + header.row { + box-sizing: content-box; } + header .logo { + color: var(--header-fore-color); + font-size: 1.75rem; + padding: var(--universal-padding) calc(2 * var(--universal-padding)); + text-decoration: none; } + header button, header [type="button"], header .button, header [role="button"] { + box-sizing: border-box; + position: relative; + top: calc(0rem - var(--universal-padding) / 4); + height: calc(3.1875rem + var(--universal-padding) / 2); + background: var(--header-back-color); + line-height: calc(3.1875rem - var(--universal-padding) * 1.5); + text-align: center; + color: var(--header-fore-color); + border: 0; + border-radius: 0; + margin: 0; + text-transform: uppercase; } + header button:hover, header button:focus, header [type="button"]:hover, header [type="button"]:focus, header .button:hover, header .button:focus, header [role="button"]:hover, header [role="button"]:focus { + background: var(--header-hover-back-color); } + +nav { + background: var(--nav-back-color); + color: var(--nav-fore-color); + border: 0.0714285714rem solid var(--nav-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); } + nav * { + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } + nav a, nav a:visited { + display: block; + color: var(--nav-link-color); + border-radius: var(--universal-border-radius); + transition: background 0.3s; } + nav a:hover, nav a:focus, nav a:visited:hover, nav a:visited:focus { + text-decoration: none; + background: var(--nav-hover-back-color); } + nav .sublink-1 { + position: relative; + margin-left: calc(2 * var(--universal-padding)); } + nav .sublink-1:before { + position: absolute; + left: calc(var(--universal-padding) - 1 * var(--universal-padding)); + top: -0.0714285714rem; + content: ''; + height: 100%; + border: 0.0714285714rem solid var(--nav-border-color); + border-left: 0; } + nav .sublink-2 { + position: relative; + margin-left: calc(4 * var(--universal-padding)); } + nav .sublink-2:before { + position: absolute; + left: calc(var(--universal-padding) - 3 * var(--universal-padding)); + top: -0.0714285714rem; + content: ''; + height: 100%; + border: 0.0714285714rem solid var(--nav-border-color); + border-left: 0; } + +footer { + background: var(--footer-back-color); + color: var(--footer-fore-color); + border-top: 0.0714285714rem solid var(--footer-border-color); + padding: calc(2 * var(--universal-padding)) var(--universal-padding); + font-size: 0.875rem; } + footer a, footer a:visited { + color: var(--footer-link-color); } + +header.sticky { + position: -webkit-sticky; + position: sticky; + z-index: 1101; + top: 0; } + +footer.sticky { + position: -webkit-sticky; + position: sticky; + z-index: 1101; + bottom: 0; } + +.drawer-toggle:before { + display: inline-block; + position: relative; + vertical-align: bottom; + content: '\00a0\2261\00a0'; + font-family: sans-serif; + font-size: 1.5em; } +@media screen and (min-width: 500px) { + .drawer-toggle:not(.persistent) { + display: none; } } + +[type="checkbox"].drawer { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + [type="checkbox"].drawer + * { + display: block; + box-sizing: border-box; + position: fixed; + top: 0; + width: 320px; + height: 100vh; + overflow-y: auto; + background: var(--drawer-back-color); + border: 0.0714285714rem solid var(--drawer-border-color); + border-radius: 0; + margin: 0; + z-index: 1110; + right: -320px; + transition: right 0.3s; } + [type="checkbox"].drawer + * .drawer-close { + position: absolute; + top: var(--universal-margin); + right: var(--universal-margin); + z-index: 1111; + width: 2rem; + height: 2rem; + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + margin: 0; + cursor: pointer; + transition: background 0.3s; } + [type="checkbox"].drawer + * .drawer-close:before { + display: block; + content: '\00D7'; + color: var(--drawer-close-color); + position: relative; + font-family: sans-serif; + font-size: 2rem; + line-height: 1; + text-align: center; } + [type="checkbox"].drawer + * .drawer-close:hover, [type="checkbox"].drawer + * .drawer-close:focus { + background: var(--drawer-hover-back-color); } + @media screen and (max-width: 320px) { + [type="checkbox"].drawer + * { + width: 100%; } } + [type="checkbox"].drawer:checked + * { + right: 0; } + @media screen and (min-width: 500px) { + [type="checkbox"].drawer:not(.persistent) + * { + position: static; + height: 100%; + z-index: 1100; } + [type="checkbox"].drawer:not(.persistent) + * .drawer-close { + display: none; } } + +/* + Definitions for the responsive table component. +*/ +/* Table module CSS variable definitions. */ +:root { + --table-border-color: #03234b; + --table-border-separator-color: #03234b; + --table-head-back-color: #03234b; + --table-head-fore-color: #ffffff; + --table-body-back-color: #ffffff; + --table-body-fore-color: #03234b; + --table-body-alt-back-color: #f4f4f4; } + +table { + border-collapse: separate; + border-spacing: 0; + margin: 0; + display: flex; + flex: 0 1 auto; + flex-flow: row wrap; + padding: var(--universal-padding); + padding-top: 0; } + table caption { + font-size: 1rem; + margin: calc(2 * var(--universal-margin)) 0; + max-width: 100%; + flex: 0 0 100%; } + table thead, table tbody { + display: flex; + flex-flow: row wrap; + border: 0.0714285714rem solid var(--table-border-color); } + table thead { + z-index: 999; + border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; + border-bottom: 0.0714285714rem solid var(--table-border-separator-color); } + table tbody { + border-top: 0; + margin-top: calc(0 - var(--universal-margin)); + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + table tr { + display: flex; + padding: 0; } + table th, table td { + padding: calc(0.5 * var(--universal-padding)); + font-size: 0.9rem; } + table th { + text-align: left; + background: var(--table-head-back-color); + color: var(--table-head-fore-color); } + table td { + background: var(--table-body-back-color); + color: var(--table-body-fore-color); + border-top: 0.0714285714rem solid var(--table-border-color); } + +table:not(.horizontal) { + overflow: auto; + max-height: 100%; } + table:not(.horizontal) thead, table:not(.horizontal) tbody { + max-width: 100%; + flex: 0 0 100%; } + table:not(.horizontal) tr { + flex-flow: row wrap; + flex: 0 0 100%; } + table:not(.horizontal) th, table:not(.horizontal) td { + flex: 1 0 0%; + overflow: hidden; + text-overflow: ellipsis; } + table:not(.horizontal) thead { + position: sticky; + top: 0; } + table:not(.horizontal) tbody tr:first-child td { + border-top: 0; } + +table.horizontal { + border: 0; } + table.horizontal thead, table.horizontal tbody { + border: 0; + flex: .2 0 0; + flex-flow: row nowrap; } + table.horizontal tbody { + overflow: auto; + justify-content: space-between; + flex: .8 0 0; + margin-left: 0; + padding-bottom: calc(var(--universal-padding) / 4); } + table.horizontal tr { + flex-direction: column; + flex: 1 0 auto; } + table.horizontal th, table.horizontal td { + width: auto; + border: 0; + border-bottom: 0.0714285714rem solid var(--table-border-color); } + table.horizontal th:not(:first-child), table.horizontal td:not(:first-child) { + border-top: 0; } + table.horizontal th { + text-align: right; + border-left: 0.0714285714rem solid var(--table-border-color); + border-right: 0.0714285714rem solid var(--table-border-separator-color); } + table.horizontal thead tr:first-child { + padding-left: 0; } + table.horizontal th:first-child, table.horizontal td:first-child { + border-top: 0.0714285714rem solid var(--table-border-color); } + table.horizontal tbody tr:last-child td { + border-right: 0.0714285714rem solid var(--table-border-color); } + table.horizontal tbody tr:last-child td:first-child { + border-top-right-radius: 0.25rem; } + table.horizontal tbody tr:last-child td:last-child { + border-bottom-right-radius: 0.25rem; } + table.horizontal thead tr:first-child th:first-child { + border-top-left-radius: 0.25rem; } + table.horizontal thead tr:first-child th:last-child { + border-bottom-left-radius: 0.25rem; } + +@media screen and (max-width: 499px) { + table, table.horizontal { + border-collapse: collapse; + border: 0; + width: 100%; + display: table; } + table thead, table th, table.horizontal thead, table.horizontal th { + border: 0; + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + table tbody, table.horizontal tbody { + border: 0; + display: table-row-group; } + table tr, table.horizontal tr { + display: block; + border: 0.0714285714rem solid var(--table-border-color); + border-radius: var(--universal-border-radius); + background: #ffffff; + padding: var(--universal-padding); + margin: var(--universal-margin); + margin-bottom: calc(1 * var(--universal-margin)); } + table th, table td, table.horizontal th, table.horizontal td { + width: auto; } + table td, table.horizontal td { + display: block; + border: 0; + text-align: right; } + table td:before, table.horizontal td:before { + content: attr(data-label); + float: left; + font-weight: 600; } + table th:first-child, table td:first-child, table.horizontal th:first-child, table.horizontal td:first-child { + border-top: 0; } + table tbody tr:last-child td, table.horizontal tbody tr:last-child td { + border-right: 0; } } +table tr:nth-of-type(2n) > td { + background: var(--table-body-alt-back-color); } + +@media screen and (max-width: 500px) { + table tr:nth-of-type(2n) { + background: var(--table-body-alt-back-color); } } +:root { + --table-body-hover-back-color: #90caf9; } + +table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { + background: var(--table-body-hover-back-color); } + +@media screen and (max-width: 500px) { + table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { + background: var(--table-body-hover-back-color); } } +/* + Definitions for contextual background elements, toasts and tooltips. +*/ +/* Contextual module CSS variable definitions */ +:root { + --mark-back-color: #3cb4e6; + --mark-fore-color: #ffffff; } + +mark { + background: var(--mark-back-color); + color: var(--mark-fore-color); + font-size: 0.95em; + line-height: 1em; + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) var(--universal-padding); } + mark.inline-block { + display: inline-block; + font-size: 1em; + line-height: 1.4; + padding: calc(var(--universal-padding) / 2) var(--universal-padding); } + +:root { + --toast-back-color: #424242; + --toast-fore-color: #fafafa; } + +.toast { + position: fixed; + bottom: calc(var(--universal-margin) * 3); + left: 50%; + transform: translate(-50%, -50%); + z-index: 1111; + color: var(--toast-fore-color); + background: var(--toast-back-color); + border-radius: calc(var(--universal-border-radius) * 16); + padding: var(--universal-padding) calc(var(--universal-padding) * 3); } + +:root { + --tooltip-back-color: #212121; + --tooltip-fore-color: #fafafa; } + +.tooltip { + position: relative; + display: inline-block; } + .tooltip:before, .tooltip:after { + position: absolute; + opacity: 0; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + transition: all 0.3s; + z-index: 1010; + left: 50%; } + .tooltip:not(.bottom):before, .tooltip:not(.bottom):after { + bottom: 75%; } + .tooltip.bottom:before, .tooltip.bottom:after { + top: 75%; } + .tooltip:hover:before, .tooltip:hover:after, .tooltip:focus:before, .tooltip:focus:after { + opacity: 1; + clip: auto; + -webkit-clip-path: inset(0%); + clip-path: inset(0%); } + .tooltip:before { + content: ''; + background: transparent; + border: var(--universal-margin) solid transparent; + left: calc(50% - var(--universal-margin)); } + .tooltip:not(.bottom):before { + border-top-color: #212121; } + .tooltip.bottom:before { + border-bottom-color: #212121; } + .tooltip:after { + content: attr(aria-label); + color: var(--tooltip-fore-color); + background: var(--tooltip-back-color); + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + white-space: nowrap; + transform: translateX(-50%); } + .tooltip:not(.bottom):after { + margin-bottom: calc(2 * var(--universal-margin)); } + .tooltip.bottom:after { + margin-top: calc(2 * var(--universal-margin)); } + +:root { + --modal-overlay-color: rgba(0, 0, 0, 0.45); + --modal-close-color: #e6007e; + --modal-close-hover-color: #ffe97f; } + +[type="checkbox"].modal { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + [type="checkbox"].modal + div { + position: fixed; + top: 0; + left: 0; + display: none; + width: 100vw; + height: 100vh; + background: var(--modal-overlay-color); } + [type="checkbox"].modal + div .card { + margin: 0 auto; + max-height: 50vh; + overflow: auto; } + [type="checkbox"].modal + div .card .modal-close { + position: absolute; + top: 0; + right: 0; + width: 1.75rem; + height: 1.75rem; + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + margin: 0; + cursor: pointer; + transition: background 0.3s; } + [type="checkbox"].modal + div .card .modal-close:before { + display: block; + content: '\00D7'; + color: var(--modal-close-color); + position: relative; + font-family: sans-serif; + font-size: 1.75rem; + line-height: 1; + text-align: center; } + [type="checkbox"].modal + div .card .modal-close:hover, [type="checkbox"].modal + div .card .modal-close:focus { + background: var(--modal-close-hover-color); } + [type="checkbox"].modal:checked + div { + display: flex; + flex: 0 1 auto; + z-index: 1200; } + [type="checkbox"].modal:checked + div .card .modal-close { + z-index: 1211; } + +:root { + --collapse-label-back-color: #03234b; + --collapse-label-fore-color: #ffffff; + --collapse-label-hover-back-color: #3cb4e6; + --collapse-selected-label-back-color: #3cb4e6; + --collapse-border-color: var(--collapse-label-back-color); + --collapse-selected-border-color: #ceecf8; + --collapse-content-back-color: #ffffff; + --collapse-selected-label-border-color: #3cb4e6; } + +.collapse { + width: calc(100% - 2 * var(--universal-margin)); + opacity: 1; + display: flex; + flex-direction: column; + margin: var(--universal-margin); + border-radius: var(--universal-border-radius); } + .collapse > [type="radio"], .collapse > [type="checkbox"] { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + .collapse > label { + flex-grow: 1; + display: inline-block; + height: 1.25rem; + cursor: pointer; + transition: background 0.2s; + color: var(--collapse-label-fore-color); + background: var(--collapse-label-back-color); + border: 0.0714285714rem solid var(--collapse-selected-border-color); + padding: calc(1.25 * var(--universal-padding)); } + .collapse > label:hover, .collapse > label:focus { + background: var(--collapse-label-hover-back-color); } + .collapse > label + div { + flex-basis: auto; + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + transition: max-height 0.3s; + max-height: 1px; } + .collapse > :checked + label { + background: var(--collapse-selected-label-back-color); + border-color: var(--collapse-selected-label-border-color); } + .collapse > :checked + label + div { + box-sizing: border-box; + position: relative; + width: 100%; + height: auto; + overflow: auto; + margin: 0; + background: var(--collapse-content-back-color); + border: 0.0714285714rem solid var(--collapse-selected-border-color); + border-top: 0; + padding: var(--universal-padding); + clip: auto; + -webkit-clip-path: inset(0%); + clip-path: inset(0%); + max-height: 100%; } + .collapse > label:not(:first-of-type) { + border-top: 0; } + .collapse > label:first-of-type { + border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; } + .collapse > label:last-of-type:not(:first-of-type) { + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + .collapse > label:last-of-type:first-of-type { + border-radius: var(--universal-border-radius); } + .collapse > :checked:last-of-type:not(:first-of-type) + label { + border-radius: 0; } + .collapse > :checked:last-of-type + label + div { + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + +/* + Custom elements for contextual background elements, toasts and tooltips. +*/ +mark.tertiary { + --mark-back-color: #3cb4e6; } + +mark.tag { + padding: calc(var(--universal-padding)/2) var(--universal-padding); + border-radius: 1em; } + +/* + Definitions for progress elements and spinners. +*/ +/* Progress module CSS variable definitions */ +:root { + --progress-back-color: #3cb4e6; + --progress-fore-color: #555; } + +progress { + display: block; + vertical-align: baseline; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 0.75rem; + width: calc(100% - 2 * var(--universal-margin)); + margin: var(--universal-margin); + border: 0; + border-radius: calc(2 * var(--universal-border-radius)); + background: var(--progress-back-color); + color: var(--progress-fore-color); } + progress::-webkit-progress-value { + background: var(--progress-fore-color); + border-top-left-radius: calc(2 * var(--universal-border-radius)); + border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } + progress::-webkit-progress-bar { + background: var(--progress-back-color); } + progress::-moz-progress-bar { + background: var(--progress-fore-color); + border-top-left-radius: calc(2 * var(--universal-border-radius)); + border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } + progress[value="1000"]::-webkit-progress-value { + border-radius: calc(2 * var(--universal-border-radius)); } + progress[value="1000"]::-moz-progress-bar { + border-radius: calc(2 * var(--universal-border-radius)); } + progress.inline { + display: inline-block; + vertical-align: middle; + width: 60%; } + +:root { + --spinner-back-color: #ddd; + --spinner-fore-color: #555; } + +@keyframes spinner-donut-anim { + 0% { + transform: rotate(0deg); } + 100% { + transform: rotate(360deg); } } +.spinner { + display: inline-block; + margin: var(--universal-margin); + border: 0.25rem solid var(--spinner-back-color); + border-left: 0.25rem solid var(--spinner-fore-color); + border-radius: 50%; + width: 1.25rem; + height: 1.25rem; + animation: spinner-donut-anim 1.2s linear infinite; } + +/* + Custom elements for progress bars and spinners. +*/ +progress.primary { + --progress-fore-color: #1976d2; } + +progress.secondary { + --progress-fore-color: #d32f2f; } + +progress.tertiary { + --progress-fore-color: #308732; } + +.spinner.primary { + --spinner-fore-color: #1976d2; } + +.spinner.secondary { + --spinner-fore-color: #d32f2f; } + +.spinner.tertiary { + --spinner-fore-color: #308732; } + +/* + Definitions for icons - powered by Feather (https://feathericons.com/). +*/ +span[class^='icon-'] { + display: inline-block; + height: 1em; + width: 1em; + vertical-align: -0.125em; + background-size: contain; + margin: 0 calc(var(--universal-margin) / 4); } + span[class^='icon-'].secondary { + -webkit-filter: invert(25%); + filter: invert(25%); } + span[class^='icon-'].inverse { + -webkit-filter: invert(100%); + filter: invert(100%); } + +span.icon-alert { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12' y2='16'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-bookmark { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-calendar { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-credit { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1' y='4' width='22' height='16' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='1' y1='10' x2='23' y2='10'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-edit { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 14.66V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h5.34'%3E%3C/path%3E%3Cpolygon points='18 2 22 6 12 16 8 16 8 12 18 2'%3E%3C/polygon%3E%3C/svg%3E"); } +span.icon-link { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'%3E%3C/path%3E%3Cpolyline points='15 3 21 3 21 9'%3E%3C/polyline%3E%3Cline x1='10' y1='14' x2='21' y2='3'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-help { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3'%3E%3C/path%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='17' x2='12' y2='17'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-home { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'%3E%3C/path%3E%3Cpolyline points='9 22 9 12 15 12 15 22'%3E%3C/polyline%3E%3C/svg%3E"); } +span.icon-info { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='16' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='8' x2='12' y2='8'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-lock { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2' ry='2'%3E%3C/rect%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-mail { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z'%3E%3C/path%3E%3Cpolyline points='22,6 12,13 2,6'%3E%3C/polyline%3E%3C/svg%3E"); } +span.icon-location { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z'%3E%3C/path%3E%3Ccircle cx='12' cy='10' r='3'%3E%3C/circle%3E%3C/svg%3E"); } +span.icon-phone { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-rss { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9'%3E%3C/path%3E%3Cpath d='M4 4a16 16 0 0 1 16 16'%3E%3C/path%3E%3Ccircle cx='5' cy='19' r='1'%3E%3C/circle%3E%3C/svg%3E"); } +span.icon-search { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-settings { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'%3E%3C/circle%3E%3Cpath d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-share { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='18' cy='5' r='3'%3E%3C/circle%3E%3Ccircle cx='6' cy='12' r='3'%3E%3C/circle%3E%3Ccircle cx='18' cy='19' r='3'%3E%3C/circle%3E%3Cline x1='8.59' y1='13.51' x2='15.42' y2='17.49'%3E%3C/line%3E%3Cline x1='15.41' y1='6.51' x2='8.59' y2='10.49'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-cart { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='21' r='1'%3E%3C/circle%3E%3Ccircle cx='20' cy='21' r='1'%3E%3C/circle%3E%3Cpath d='M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-upload { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'%3E%3C/path%3E%3Cpolyline points='17 8 12 3 7 8'%3E%3C/polyline%3E%3Cline x1='12' y1='3' x2='12' y2='15'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-user { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'%3E%3C/path%3E%3Ccircle cx='12' cy='7' r='4'%3E%3C/circle%3E%3C/svg%3E"); } + +/* + Definitions for utilities and helper classes. +*/ +/* Utility module CSS variable definitions */ +:root { + --generic-border-color: rgba(0, 0, 0, 0.3); + --generic-box-shadow: 0 0.2857142857rem 0.2857142857rem 0 rgba(0, 0, 0, 0.125), 0 0.1428571429rem 0.1428571429rem -0.1428571429rem rgba(0, 0, 0, 0.125); } + +.hidden { + display: none !important; } + +.visually-hidden { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } + +.bordered { + border: 0.0714285714rem solid var(--generic-border-color) !important; } + +.rounded { + border-radius: var(--universal-border-radius) !important; } + +.circular { + border-radius: 50% !important; } + +.shadowed { + box-shadow: var(--generic-box-shadow) !important; } + +.responsive-margin { + margin: calc(var(--universal-margin) / 4) !important; } + @media screen and (min-width: 500px) { + .responsive-margin { + margin: calc(var(--universal-margin) / 2) !important; } } + @media screen and (min-width: 1280px) { + .responsive-margin { + margin: var(--universal-margin) !important; } } + +.responsive-padding { + padding: calc(var(--universal-padding) / 4) !important; } + @media screen and (min-width: 500px) { + .responsive-padding { + padding: calc(var(--universal-padding) / 2) !important; } } + @media screen and (min-width: 1280px) { + .responsive-padding { + padding: var(--universal-padding) !important; } } + +@media screen and (max-width: 499px) { + .hidden-sm { + display: none !important; } } +@media screen and (min-width: 500px) and (max-width: 1279px) { + .hidden-md { + display: none !important; } } +@media screen and (min-width: 1280px) { + .hidden-lg { + display: none !important; } } +@media screen and (max-width: 499px) { + .visually-hidden-sm { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } +@media screen and (min-width: 500px) and (max-width: 1279px) { + .visually-hidden-md { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } +@media screen and (min-width: 1280px) { + .visually-hidden-lg { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } + +/*# sourceMappingURL=mini-custom.css.map */ + +img[alt="ST logo"] { display: block; margin: auto; width: 75%; max-width: 250px; min-width: 71px; } +img[alt="Cube logo"] { float: right; width: 30%; max-width: 10rem; min-width: 8rem; padding-right: 1rem;} + +.figure { + display: block; + margin-left: auto; + margin-right: auto; + text-align: center; +} diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/st_logo_2020.png b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/st_logo_2020.png new file mode 100644 index 0000000000000000000000000000000000000000..d6cebb5ac70e0594cbe37a6b60036a80ef3bed37 GIT binary patch literal 7520 zcmcI|WmKC@*KTl!K!Z~t6qn*&DDF_CK%q#B6QmH_DHL}I6b%;K-J$eBN|2xh0+bea zmtyV5bG|?CpZBcu=iF<}z4q*xz1LhL*PcBwx;m;Pgmi=e0DweYO-UaBz)*UWZ}4#+ zCC-V!SC16}H#HLv0Dy?%--0o{5_}H;Jf%=ql7H=+dziOk_)KzUSaiQ9L<^g!49k}} z?4y$V zrsn3Ul^TY`00G_J_8;F7Sr5c3Y)f-yOYl{fS0avfKJg7R%r!y-ohcBkr6XBZBkE)( z_t+tVV2}G1_CN!)yWes*wa-AGwk31N_T1`)4COlfz+o(9S90e?6jHV4)!>`j+oRqp z)gb?rtSdw<#&c?q!OKB+Ncn!kr5JR2EYan8HAPXBw*Oh-F(6GmaC!`$p7fl!_Cdu> z5@PUMR_K5&jgevDepWqepZVdMHR$q>ga=7k0ltW$HHVn>HRa!#(+BW_jN$5rx^MtR zzWT7tNWQeFzEp+86jOYI=I)*GZYEiXlf-Mw%tJ^ptL%2)%#PmUjxC4wx@%KxQ)8kO?|7E1 zd@5gd9_$*6nx?fj*iF_EJT*PYLFP}d8*Fw>cu3@&nm%V_C}V7HMmg|Nl#1J1^#)uz zZag|X>{6j-myvL}3(H8o3resNBq_jcuJuyT!QuXnNN&zG^tG? z>y*dy1#XfwyCE#UiLT(~LYAVwp)epErJLsHBA|l0xo)kxLAPob+7tFlr{7x8(#v|O zknK}QC6|~=cTJ0;x9MWMKua;LdTKIHX>35a@7{5y0MQ|zqsP64mM~`gJ&&R{pSUBA zf3Y>k>d|xdzBFztjtO~{y%@LUdwSgzEj=69hH3-NNWx7<|49%2%lvTEeE3_|$~iDd zlktnxf|NB>Bui)yY;%TXgWA;rhODxR!-4GzxKd473I)3;j zS4-Vun<^vqZ4)HbwVzq%5%)S!>Q(Y&PkF ze1ab_oy?_$PZT-mKJ3K^;6MrB*Wc$lkYJ_460AFYEq{AjlDxm;5GRwOsm>doJy3Z;a$FSu-q`X)Hw&o~?_`Dnpx4dOj6#)bGOdZbj4hD`l|&#v~K+WrGO zpLCVQg=*h=4H1sK)D*Pxtb#p`c+g-eK65k!CEZjLIrfm}5<4@KVqZ#8(S$vs{?Xv) zN(}CKeeLR%I)W!p(l-`utKmBbJk-On{)ciqUN5%?TS8uwKU(8}Mxhsb&qHL~DDcB@qi} z4z%efV#K69a#lShPt5}*7ME@^xunFR{k;|qp z`_Hgdj_Qle?%Ydlr3f^SdRkUncIj7qTiu85tA$v`#419Nlof8tjqUjO z!Rwyq$Krfh`(@MiE+)yie&jU^crprYV&?zN!2b33S2qtW+zB$nahDhVZiQ12bmcwYBcT8KS>v`jsuI@X zy^k^7>TM5Ndp@}pSl6vmkk*u`@C`z(gq||K2>y=Y#w1i`Nk2zAP7{_^ACq;bQmT<4 z;b~K3=?mhZX#~jQnZjdU={NFp^HRr~;^PXQ*UIHzkq}Xsn!56*ZCOOEt|^ zawUwGqs;zCEGKTz&(a(@h#0sCE+@`3Y<&}9!(;Pw&`C+d#D?`##&!@*ERaH0fksrh zfk2svh3!d~h{SC6BNKN2j6(lzC>S^_*eh{@gR zP$rV4$nqV1y|zYpd;nQr-`Vlp(5sQXx9AibC?xc7pUV)v2cWfHu3{KLbfP;;;`I&)mWqLcXt6s+5fps9R?K>hGR$5;=( zo#;zzQ5!w+(99p1_gh^?F#$tpMd+4%G|K`XG_#@A>30WD2L9!0a>wRASg`M?^z#)| zifb$d^KUD&3qLsr-@}r_7p${gdmRqhy819bj?yI-v({I?0o3_8d>CZmCzqH4{{QtD z|6dvgm<^~668G`6wLw4C4y-o9E9ZG3RiH^&;rrKSBT@bMR+!TlYo*9P;?Z>xORMV3ndQp9EyNn!!~j&x&$gDVke|t#!{QoegHm+sT7cSjwSu z)jZlx1pHrrx0&YCZWJ4xC&U%r_IwfJOxnYqYMcZn&_hgnKuls z>(Y$qjIhcweo^A_VVq_#UR&urF%UbI^><5L5zbV9owMQviM*_{@i|dke!!v8a_yG! zl%#ay{(6U_N3-)yeif3tx6>aQSf1r zO~OuNW<8a~bi6Xby0@tKw0@f1R!@+3S2nf#F&j~l0mrNCtjoZdPYob?g!Vx4F-uA2 z4uS>8eR?dA9i>C|cm-m5lO0m@$f(DB6Z<9Pe07xR`l4$ks3eZ@v5}1?^YNQy-tB(` zgUNZrGVf#b~`}jew;MQG1O~VDk_i*<)p9DfFfd;vLy4QZT zMYh|DxJg3-!{szUN*uo&`&DUkzq4qG2`Lj;Ar46DYUymcviS{Unhzmx z=LwZ-Lr{t1z?9Oip%!z{j+Z%_@u?C78I`V4fC`icG1c|2;`EoLK$ z)9|wrAV&V1Vgts~tQCw0X?X{74W"NJQ zW3BP!5c~4zzHJScwQK9L_%m%L`*q{1aW_3rObki~B~=Dwp`;@w`>xZ6;L_6oR^ecEcmup`yb}lgsmv zQByrxc)Qqm(Hwmq%fLjqcrJ5QR?z_*vb~Iy~RXUY8u-D8AqTzetwNNA8~N z$j&1>#IrkSslUqXW|l}q_TlTVKAjRI@~7(GLf4M>GM!3u_)y6ORe6BQUmrQ16%OdZKo(?AYXK$u@=)TPUi1EZaLBu zuEB(5GX2vcoHS%zMUW!DZ)&xRo@mhouk|hMgHIG>cO-Ah(0AMNlq@?cPpy==-!#qR zBov7l3G?P*KM(vU;Apo-(-Bw;sdQJkh~r)W$KRQKd!#(A8M34^MhD10Ra={AqSvjy z3>PkgA}f^@Rg1$dX=jaEB_V%_vn(W<111_s!g>CYrcwJTJ63Eeg6{_C`aMQIgKctR zHMjkr+y6gK!v6=6;CGl#?PqmiX`A@dmmvZ}-X$*q8}G(xq|voo`=$YZuQAa8f9ApK z1VQiEUQC=OO{|Nc8ZrXH208X|XCzIRO?+Nb55Jt@va9hqBpv)uY6ma-csvSlJoJOC zK;w~s?#r)K@gm*;((JsWHU-KvFTF)q>AzwPq)I+}OrSpxh!-CM1VEMfw1fpfVL7p{ z)I$rNp5kPYDsvXL>8nV{#0fa*lm`Z;0Z=c^1qveY2uk&7nhMRl`0EsvUuvwdF&o)PCVN3wmFBPegWzooF6y~b} zY>X2;LO~&rbvx59?(4^aR+s1C6hI4r&x9Q9jL9);KZEw_x%TWZXaMzK6|2XG9$IU% zkEq}t^YOaa4s`%7F31X-#SfMgNp+4R=g2G|O^W)6^2fEsmkTTaVhKCip+3qWuN8?y zaSD_k6%-@Ifhm`z02=ZWA-pi5`A=7ztHWpP2K5rCW{>!wIUOYrH``#bz>qVSH76=8 zyJ!sNBxt;dMTn}yzUTCq1!w;N7pzb?WJrQ50W+`meL{k8i0VhFsPUz(07k`l` zg1Ifl1fc-^p^MQCpK~Jk&L!*mWfNA!&MSu`sPmti>K-;I5Dk00nB3vOl4!JwjEx^X zWQsIp2Ea_>`9f@%zGl4i3FAO9=e$2^b_>_I*dqiLJ=@TejStM?^yX$9dW`#ha)PEF zPr0zUJX!j-juYK*olG_9axQniXhF|E}oSTG_S)FZ3sN4T@q zy{l;!{UGc};YVaT97tx3s7P$WsW2^*I+Hy;vqndG!9S?tZtDIRif1=bBsqtW-n7$O zWy}Z%jKSkgLX#1p>|#4l-!$c+kA`++Ixv(Rm`;Ilb3q3tD|QjaPQ8)BJ=8R*15?nL zJR{yuqOG&!JrSZ${#NY#b!k)yDajQ$A}fUQhe7ueN6h2Pj3wY5eo|7$PaJD zM69(ee1qlSyLn)Ln6)o53Lj)elqG}gb^c}qd(q&$8B5N%nSvEjUIoEXO^obv=A7QGZzNzjO*H=*b2!86Wnqdy~8ePkq@1D1)Q^O)JG;fUCV z`rgD}dJ{7BUyBbgoTL91w^q-CfBpDr?0R38`L%p9&Q#%r*@=9p-Ioqy+WscLq?jq5 zfyYNkxr7w)-(!c85mt!FjNJ4UE6P8p8sc#Kb4L1N3!yaCo9@t3n8s}K)1!w8x77xU zo-NY3SR*Pgt#~7F;y^J&Y%z^+C9wu;hN|TC7dqSHOB&kE)Q)6Ad(l&+tA@$@w0bhJ z6xc6EJ6nm{=|V7Vo&qcXc4i)D?X0Uk$p7~iI#ci?#fxvM z78`u%m5S@^_F;_foidufzP z&ueh-zU1yM&8~0lmOfkio-gBex`)?hCJcI8Jv*R0c|WUqSq z?RU?Rmm=3t_2C%%UW9c*D%T{T{EjryCKnsz9-*Bs0}M*xS&-odhCK5eS_Eqi&c6J4o|f&;uUT=p7Fedw#EUl4%Jv{w zq-cCF^otBvw~~$yj6O>>;VqU)3Ml&Atm$B(Ht8=+&x2VS5aWD&t*+04{@k^Gn~yHY zWYC%@ld;g_qz=k*;Iv&xs5M85cEZCU&n2Baf>R6*bN>V|!)eF&l#C93eAMLD=ZF7= zOISFfB5P;F!ngWD3jfMJE_53F&dFc{h2TwSbT*(h6!c}_5_UFeB_*DiyCrtQ7Byr@ z-aCWVt?J}YP7-lfelbrCgZ5mdv(^W&Yf^OvpI}#NbS1Lc`r4&t#3kM!utm&#a;?GR z-1FusfX7&?a9h`%8wf-ub7UXp44xm4w04)S$}}_hPqn-#IabO^bo6$K07>?%G5Xs( zA$*lz_K>lAJ_o<;fsP-*-%~O(716KRqVq+X@=5J~Z~bba(yWL`;EN`@Mr2it&Lkgb z&I|R5!`ZSk%)xFX*FYDaAh=5qWSY@rx1Du9J$$=lh#!~NcFJM&aOv)eqg_@`i^zJCR9a%_{k_i%msw5q z*3!~#Xx3r|VaAwiG}~9M#c`=$Uk6~xe)47ymW+;0DD_lV67L#ouJBa7mF{)X^?eIvPdOMu4ksr`jUP$~{x@?ev2 zdX#ite2RMim01PEg`;qfwg^;v8nx9F!CtNCvz)V{PVgCs*;_@_Rk*oLx@f7hJ7^^1 zu66b)mb!ZMXLZ%8dj-+JCMoWS-Wji-Q-~U7Pt~UiXMej8JcNjk<6?Wk9eLBIhu&Vo^0;AH> z;Q5^a!NZhP(vDfBv&?jdnQavv#8N0E{ZEgs>|1)qYo^t5 zIV$g~`C2%g$*(z4)8hJlK2mF-MJW#3%Cs6`uAvsgRtTo8n!Et)1pZx@_9I18 zw7ER9v~DyrC*R$do9aEw5r@B)YzHOLB^-c9Eu9D!sFmI8^VljVKE89{zY_8PTSF+J b^}%0^qYmp2WD(pA|JtZ4>nPPKybJpu3@X?! literal 0 HcmV?d00001 diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.c b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.c new file mode 100644 index 000000000..952ff16c9 --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.c @@ -0,0 +1,886 @@ +/** + ****************************************************************************** + * @file tcpp0203.c + * @author MCD Application Team + * @brief This file provides the TCPP02/03 Type-C port protection driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "tcpp0203.h" + +#if defined(_TRACE) +#include "usbpd_core.h" +#include "usbpd_trace.h" +#include "string.h" +#include "stdio.h" +#endif /* _TRACE */ + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Components + * @{ + */ + +/** @addtogroup TCPP0203 + * @brief This file provides a set of functions needed to drive the + * TCPP02/03 Type-C port protection. + * @{ + */ + +/** @defgroup TCPP0203_Private_Constants Private Constants + * @{ + */ + +/* Compilation option in order to enable/disable a concistency check performed + after each I2C access into TCPP0203 registers : goal is to check that written value in Reg0 + is properly reflected into reg1 register content. + To enable register consistency check, please uncomment below definition. + To disable it, comment below line */ +/* #define TCPP0203_REGISTER_CONSISTENCY_CHECK */ + +/** @defgroup TCPP0203_Private_Types Private Types + * @{ + */ +/* TCPP02/03 Type-C port protection driver structure initialization */ +TCPP0203_Drv_t TCPP0203_Driver = +{ + TCPP0203_Init, + TCPP0203_DeInit, + TCPP0203_Reset, + TCPP0203_SetVConnSwitch, + TCPP0203_SetGateDriverProvider, + TCPP0203_SetGateDriverConsumer, + TCPP0203_SetPowerMode, + TCPP0203_SetVBusDischarge, + TCPP0203_SetVConnDischarge, + TCPP0203_GetVConnSwitchAck, + TCPP0203_GetGateDriverProviderAck, + TCPP0203_GetGateDriverConsumerAck, + TCPP0203_GetPowerModeAck, + TCPP0203_GetVBusDischargeAck, + TCPP0203_GetVConnDischargeAck, + TCPP0203_GetOCPVConnFlag, + TCPP0203_GetOCPVBusFlag, + TCPP0203_GetOVPVBusFlag, + TCPP0203_GetOVPCCFlag, + TCPP0203_GetOTPFlag, + TCPP0203_GetVBusOkFlag, + TCPP0203_ReadTCPPType, + TCPP0203_ReadVCONNPower, + TCPP0203_WriteCtrlRegister, + TCPP0203_ReadAckRegister, + TCPP0203_ReadFlagRegister, +}; + +/** + * @} + */ + +/** @defgroup TCPP0203_Private_Variables Private Variables + * @{ + */ +static uint8_t TCPP0203_DeviceType = TCPP0203_DEVICE_TYPE_03; + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) +static uint8_t Reg0_Expected_Value = 0x00; +static uint8_t Reg1_LastRead_Value = 0x00; +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/** @defgroup TCPP0203_Private_Function_Prototypes TCPP0203 Private Function Prototypes + * @{ + */ +static int32_t TCPP0203_ReadRegWrap(const void *handle, uint8_t Reg, uint8_t *Data, uint8_t Length); +static int32_t TCPP0203_WriteRegWrap(const void *handle, uint8_t Reg, uint8_t *Data, uint8_t Length); + +static int32_t TCPP0203_ModifyReg0(TCPP0203_Object_t *pObj, uint8_t Value, uint8_t Mask); + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) +static int32_t TCPP0203_CheckReg0Reg1(TCPP0203_Object_t *pObj, uint8_t Reg0ExpectedValue); +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + +/** + * @} + */ + +/** @defgroup TCPP0203_Exported_Functions TCPP0203 Exported Functions + * @{ + */ + +/** + * @brief Register Bus Io to component + * @param Component object pointer + * @retval Status of execution + */ +int32_t TCPP0203_RegisterBusIO(TCPP0203_Object_t *pObj, TCPP0203_IO_t *pIO) +{ + int32_t ret; + + if (pObj == NULL) + { + ret = TCPP0203_ERROR; + } + else + { + pObj->IO.Init = pIO->Init; + pObj->IO.DeInit = pIO->DeInit; + pObj->IO.Address = pIO->Address; + pObj->IO.WriteReg = pIO->WriteReg; + pObj->IO.ReadReg = pIO->ReadReg; + pObj->IO.GetTick = pIO->GetTick; + + pObj->Ctx.ReadReg = TCPP0203_ReadRegWrap; + pObj->Ctx.WriteReg = TCPP0203_WriteRegWrap; + pObj->Ctx.handle = pObj; + + if (pObj->IO.Init != NULL) + { + ret = pObj->IO.Init(); + } + else + { + ret = TCPP0203_ERROR; + } + } + + return ret; +} + +/** + * @brief Initializes the TCPP0203 interface + * @param pObj Pointer to component object + * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) + */ +int32_t TCPP0203_Init(TCPP0203_Object_t *pObj) +{ + int32_t ret = 0; + uint8_t tmp; + + if (pObj->IsInitialized == 0U) + { + /* Read TCPP Device type */ + ret += tcpp0203_read_reg(&pObj->Ctx, TCPP0203_READ_REG2, &tmp, 1); + + if (ret == TCPP0203_OK) + { + TCPP0203_DeviceType = (tmp & TCPP0203_DEVICE_TYPE_MSK); + } + else + { + TCPP0203_DeviceType = TCPP0203_DEVICE_TYPE_02; + } + pObj->IsInitialized = 1U; + } + + if (ret != TCPP0203_OK) + { + ret = TCPP0203_ERROR; + } + + return ret; +} + +/** + * @brief Deinitializes the TCPP0203 interface + * @param pObj Pointer to component object + * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) + */ +int32_t TCPP0203_DeInit(TCPP0203_Object_t *pObj) +{ + if (pObj->IsInitialized == 1U) + { + /* De-Initialize IO BUS layer */ + pObj->IO.DeInit(); + + pObj->IsInitialized = 0U; + } + + return TCPP0203_OK; +} + +/** + * @brief Resets TCPP0203 register (Reg0) + * @param pObj Pointer to component object + * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) + */ +int32_t TCPP0203_Reset(TCPP0203_Object_t *pObj) +{ + int32_t ret = TCPP0203_OK; + uint8_t tmp = TCPP0203_REG0_RST_VALUE; + + /* Write reset values in Reg0 register */ + if (tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, &tmp, 1) != TCPP0203_OK) + { + ret = TCPP0203_ERROR; + } + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) + Reg0_Expected_Value = TCPP0203_REG0_RST_VALUE; + Reg1_LastRead_Value = TCPP0203_REG0_RST_VALUE; +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + + return ret; +} + +/** + * @brief Configure TCPP0203 VConn Switch + * @param pObj Pointer to component object + * @param VConnSwitch VConn Switch requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_VCONN_SWITCH_OPEN VConn switch open + * @arg TCPP0203_VCONN_SWITCH_CC1 VConn closed on CC1 + * @arg TCPP0203_VCONN_SWITCH_CC2 VConn closed on CC2 + * @retval Component status + */ +int32_t TCPP0203_SetVConnSwitch(TCPP0203_Object_t *pObj, uint8_t VConnSwitch) +{ + int32_t ret = TCPP0203_OK; + + if ((VConnSwitch != TCPP0203_VCONN_SWITCH_OPEN) + && (VConnSwitch != TCPP0203_VCONN_SWITCH_CC1) + && (VConnSwitch != TCPP0203_VCONN_SWITCH_CC2)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update VConn switch setting in Writing register Reg0 */ + ret += TCPP0203_ModifyReg0(pObj, VConnSwitch, TCPP0203_VCONN_SWITCH_MSK); + } + + return ret; +} + +/** + * @brief Configure TCPP0203 Gate Driver for Provider path + * @param pObj Pointer to component object + * @param GateDriverProvider GDP switch load requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_GD_PROVIDER_SWITCH_OPEN GDP Switch Load Open + * @arg TCPP0203_GD_PROVIDER_SWITCH_CLOSED GDP Switch Load closed + * @retval Component status + */ +int32_t TCPP0203_SetGateDriverProvider(TCPP0203_Object_t *pObj, uint8_t GateDriverProvider) +{ + int32_t ret = TCPP0203_OK; + + if ((GateDriverProvider != TCPP0203_GD_PROVIDER_SWITCH_OPEN) + && (GateDriverProvider != TCPP0203_GD_PROVIDER_SWITCH_CLOSED)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update GDP Switch Load setting in Writing register Reg0 */ + if (GateDriverProvider == TCPP0203_GD_PROVIDER_SWITCH_CLOSED) + { + /* If Gate Driver Provider is to be closed, Gate Driver Consumer should be open */ + ret += TCPP0203_ModifyReg0(pObj, (GateDriverProvider | TCPP0203_GD_CONSUMER_SWITCH_OPEN), + (TCPP0203_GD_PROVIDER_SWITCH_MSK | TCPP0203_GD_CONSUMER_SWITCH_MSK)); + } + else + { + ret += TCPP0203_ModifyReg0(pObj, GateDriverProvider, TCPP0203_GD_PROVIDER_SWITCH_MSK); + } + } + + return ret; +} + +/** + * @brief Configure TCPP0203 Gate Driver for Consumer path + * @param pObj Pointer to component object + * @param GateDriverConsumer GDC switch load requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_GD_CONSUMER_SWITCH_OPEN GDC Switch Load Open + * @arg TCPP0203_GD_CONSUMER_SWITCH_CLOSED GDC Switch Load closed + * @retval Component status + */ +int32_t TCPP0203_SetGateDriverConsumer(TCPP0203_Object_t *pObj, uint8_t GateDriverConsumer) +{ + int32_t ret = TCPP0203_OK; + + /* Check if TCPP type is TCPP03. Otherwise, return error */ + if (TCPP0203_DeviceType != TCPP0203_DEVICE_TYPE_03) + { + return (TCPP0203_ERROR); + } + + if ((GateDriverConsumer != TCPP0203_GD_CONSUMER_SWITCH_OPEN) + && (GateDriverConsumer != TCPP0203_GD_CONSUMER_SWITCH_CLOSED)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update GDC Switch Load setting in Writing register Reg0 */ + if (GateDriverConsumer == TCPP0203_GD_CONSUMER_SWITCH_CLOSED) + { + /* If Gate Driver Consumer is to be closed, Gate Driver Provider should be open */ + ret += TCPP0203_ModifyReg0(pObj, (GateDriverConsumer | TCPP0203_GD_PROVIDER_SWITCH_OPEN), + (TCPP0203_GD_PROVIDER_SWITCH_MSK | TCPP0203_GD_CONSUMER_SWITCH_MSK)); + } + else + { + ret += TCPP0203_ModifyReg0(pObj, GateDriverConsumer, TCPP0203_GD_CONSUMER_SWITCH_MSK); + } + } + + return ret; +} + +/** + * @brief Configure TCPP0203 Power Mode + * @param pObj Pointer to component object + * @param PowerMode Power mode requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_POWER_MODE_HIBERNATE Hibernate + * @arg TCPP0203_POWER_MODE_LOWPOWER Low Power + * @arg TCPP0203_POWER_MODE_NORMAL Normal + * @retval Component status + */ +int32_t TCPP0203_SetPowerMode(TCPP0203_Object_t *pObj, uint8_t PowerMode) +{ + int32_t ret = TCPP0203_OK; + + if ((PowerMode != TCPP0203_POWER_MODE_HIBERNATE) + && (PowerMode != TCPP0203_POWER_MODE_LOWPOWER) + && (PowerMode != TCPP0203_POWER_MODE_NORMAL)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update Power Mode setting in Writing register Reg0 */ + ret += TCPP0203_ModifyReg0(pObj, PowerMode, TCPP0203_POWER_MODE_MSK); + } + + return ret; +} + +/** + * @brief Configure TCPP0203 Gate Driver for Provider path + * @param pObj Pointer to component object + * @param VBusDischarge VBUS Discharge requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_VBUS_DISCHARGE_OFF VBUS Discharge Off + * @arg TCPP0203_VBUS_DISCHARGE_ON VBUS Discharge On + * @retval Component status + */ +int32_t TCPP0203_SetVBusDischarge(TCPP0203_Object_t *pObj, uint8_t VBusDischarge) +{ + int32_t ret = TCPP0203_OK; + + if ((VBusDischarge != TCPP0203_VBUS_DISCHARGE_OFF) + && (VBusDischarge != TCPP0203_VBUS_DISCHARGE_ON)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update VBUS Discharge setting in Writing register Reg0 */ + ret += TCPP0203_ModifyReg0(pObj, VBusDischarge, TCPP0203_VBUS_DISCHARGE_MSK); + } + + return ret; +} + +/** + * @brief Configure TCPP0203 Gate Driver for Provider path + * @param pObj Pointer to component object + * @param VConnDischarge GDP switch load requested setting + * This parameter can be one of the following values: + * @arg TCPP0203_VCONN_DISCHARGE_OFF VConn Discharge Off + * @arg TCPP0203_VCONN_DISCHARGE_ON VConn Discharge On + * @retval Component status + */ +int32_t TCPP0203_SetVConnDischarge(TCPP0203_Object_t *pObj, uint8_t VConnDischarge) +{ + int32_t ret = TCPP0203_OK; + + if ((VConnDischarge != TCPP0203_VCONN_DISCHARGE_OFF) + && (VConnDischarge != TCPP0203_VCONN_DISCHARGE_ON)) + { + ret = TCPP0203_ERROR; + } + else + { + /* Update VConn Discharge setting in Writing register Reg0 */ + ret += TCPP0203_ModifyReg0(pObj, VConnDischarge, TCPP0203_VCONN_DISCHARGE_MSK); + } + + return ret; +} + +/** + * @brief Get VConn switch Ack value + * @param pObj Pointer to component object + * @param pVConnSwitchAck Pointer on VConn switch Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_VCONN_SWITCH_OPEN VConn switch open Ack + * @arg TCPP0203_VCONN_SWITCH_CC1 VConn closed on CC1 Ack + * @arg TCPP0203_VCONN_SWITCH_CC2 VConn closed on CC2 Ack + * @retval Component status + */ +int32_t TCPP0203_GetVConnSwitchAck(TCPP0203_Object_t *pObj, uint8_t *pVConnSwitchAck) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pVConnSwitchAck = (tmp & TCPP0203_VCONN_SWITCH_ACK_MSK); + + return ret; +} + +/** + * @brief Get Gate Driver Provider Ack value + * @param pObj Pointer to component object + * @param pGateDriverProviderAck Pointer on Gate Driver Provider Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_GD_PROVIDER_SWITCH_ACK_OPEN Gate Driver Provider Open Ack + * @arg TCPP0203_GD_PROVIDER_SWITCH_ACK_CLOSED Gate Driver Provider Closed Ack + * @retval Component status + */ +int32_t TCPP0203_GetGateDriverProviderAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverProviderAck) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pGateDriverProviderAck = (tmp & TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK); + + return ret; +} + +/** + * @brief Get Gate Driver Consumer Ack value + * @param pObj Pointer to component object + * @param pGateDriverConsumerAck Pointer on Gate Driver Consumer Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_GD_CONSUMER_SWITCH_ACK_OPEN Gate Driver Consumer Open Ack + * @arg TCPP0203_GD_CONSUMER_SWITCH_ACK_CLOSED Gate Driver Consumer Closed Ack + * @retval Component status + */ +int32_t TCPP0203_GetGateDriverConsumerAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverConsumerAck) +{ + int32_t ret; + uint8_t tmp; + + /* Check if TCPP type is TCPP03. Otherwise, return error */ + if (TCPP0203_DeviceType != TCPP0203_DEVICE_TYPE_03) + { + return (TCPP0203_ERROR); + } + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pGateDriverConsumerAck = (tmp & TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK); + + return ret; +} + +/** + * @brief Get Power Mode Ack value + * @param pObj Pointer to component object + * @param pPowerModeAck Pointer on Power Mode Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_POWER_MODE_ACK_HIBERNATE Power Mode Hibernate Ack + * @arg TCPP0203_POWER_MODE_ACK_LOWPOWER Power Mode Low Power Ack + * @arg TCPP0203_POWER_MODE_ACK_NORMAL Power Mode Normal Ack + * @retval Component status + */ +int32_t TCPP0203_GetPowerModeAck(TCPP0203_Object_t *pObj, uint8_t *pPowerModeAck) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pPowerModeAck = (tmp & TCPP0203_POWER_MODE_ACK_MSK); + + return ret; +} + +/** + * @brief Get VBUS Discharge Ack value + * @param pObj Pointer to component object + * @param pVBusDischargeAck Pointer on VBUS Discharge Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_VBUS_DISCHARGE_ACK_OFF VBUS Discharge Off Ack + * @arg TCPP0203_VBUS_DISCHARGE_ACK_ON VBUS Discharge On Ack + * @retval Component status + */ +int32_t TCPP0203_GetVBusDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVBusDischargeAck) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pVBusDischargeAck = (tmp & TCPP0203_VBUS_DISCHARGE_ACK_MSK); + + return ret; +} + +/** + * @brief Get VConn Discharge Ack value + * @param pObj Pointer to component object + * @param pVConnDischargeAck Pointer on VConn Discharge Ack value + * This output parameter can be one of the following values: + * @arg TCPP0203_VCONN_DISCHARGE_ACK_OFF VConn Discharge Off Ack + * @arg TCPP0203_VCONN_DISCHARGE_ACK_ON VConn Discharge On Ack + * @retval Component status + */ +int32_t TCPP0203_GetVConnDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVConnDischargeAck) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + *pVConnDischargeAck = (tmp & TCPP0203_VCONN_DISCHARGE_ACK_MSK); + + return ret; +} + +/** + * @brief Get OCP VConn Flag value + * @param pObj Pointer to component object + * @param pOCPVConnFlag Pointer on OCP VConn Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_OCP_VCONN_RESET OCP VConn flag not set + * @arg TCPP0203_FLAG_OCP_VCONN_SET OCP VConn flag set + * @retval Component status + */ +int32_t TCPP0203_GetOCPVConnFlag(TCPP0203_Object_t *pObj, uint8_t *pOCPVConnFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pOCPVConnFlag = (tmp & TCPP0203_FLAG_OCP_VCONN_MSK); + + return ret; +} + +/** + * @brief Get OCP VBUS Flag value + * @param pObj Pointer to component object + * @param pGetOCPVBusFlag Pointer on OCP VBUS Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_OCP_VBUS_RESET OCP VBUS flag not set + * @arg TCPP0203_FLAG_OCP_VBUS_SET OCP VBUS flag set + * @retval Component status + */ +int32_t TCPP0203_GetOCPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pGetOCPVBusFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pGetOCPVBusFlag = (tmp & TCPP0203_FLAG_OCP_VBUS_MSK); + + return ret; +} + +/** + * @brief Get OVP VBUS Flag value + * @param pObj Pointer to component object + * @param pOVPVBusFlag Pointer on OVP VBUS Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_OVP_VBUS_RESET OVP VBUS flag not set + * @arg TCPP0203_FLAG_OVP_VBUS_SET OVP VBUS flag set + * @retval Component status + */ +int32_t TCPP0203_GetOVPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPVBusFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pOVPVBusFlag = (tmp & TCPP0203_FLAG_OVP_VBUS_MSK); + + return ret; +} + +/** + * @brief Get OVP CC Flag value + * @param pObj Pointer to component object + * @param pOVPCCFlag Pointer on OVP CC Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_OVP_CC_RESET OVP CC flag not set + * @arg TCPP0203_FLAG_OVP_CC_SET OVP CC flag set + * @retval Component status + */ +int32_t TCPP0203_GetOVPCCFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPCCFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pOVPCCFlag = (tmp & TCPP0203_FLAG_OVP_CC_MSK); + + return ret; +} + +/** + * @brief Get Over Temperature Flag value + * @param pObj Pointer to component object + * @param pOTPFlag Pointer on Over Temperature Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_OTP_RESET Over Temperature flag not set + * @arg TCPP0203_FLAG_OTP_SET Over Temperature flag set + * @retval Component status + */ +int32_t TCPP0203_GetOTPFlag(TCPP0203_Object_t *pObj, uint8_t *pOTPFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pOTPFlag = (tmp & TCPP0203_FLAG_OTP_MSK); + + return ret; +} + +/** + * @brief Get VBUS OK Flag value + * @param pObj Pointer to component object + * @param pVBusOkFlag Pointer on VBUS OK Flag value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_VBUS_OK_RESET VBUS OK flag not set + * @arg TCPP0203_FLAG_VBUS_OK_SET VBUS OK flag set + * @retval Component status + */ +int32_t TCPP0203_GetVBusOkFlag(TCPP0203_Object_t *pObj, uint8_t *pVBusOkFlag) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pVBusOkFlag = (tmp & TCPP0203_FLAG_VBUS_OK_MSK); + + return ret; +} + +/** + * @brief Get TCPP0203 Device Type value + * @param pObj Pointer to component object + * @param pTCPPType Pointer on TCPP0203 Device Type value + * This output parameter can be one of the following values: + * @arg TCPP0203_DEVICE_TYPE_02 TCPP02 Type + * @arg TCPP0203_DEVICE_TYPE_03 TCPP03 Type + * @retval Component status + */ +int32_t TCPP0203_ReadTCPPType(TCPP0203_Object_t *pObj, uint8_t *pTCPPType) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pTCPPType = (tmp & TCPP0203_DEVICE_TYPE_MSK); + + return ret; +} + +/** + * @brief Get VConn Power value + * @param pObj Pointer to component object + * @param pVCONNPower Pointer on VConn Power value + * This output parameter can be one of the following values: + * @arg TCPP0203_FLAG_VCONN_PWR_1W OCP VConn flag not set + * @arg TCPP0203_FLAG_VCONN_PWR_0_1W OCP VConn flag set + * @retval Component status + */ +int32_t TCPP0203_ReadVCONNPower(TCPP0203_Object_t *pObj, uint8_t *pVCONNPower) +{ + int32_t ret; + uint8_t tmp; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); + *pVCONNPower = (tmp & TCPP0203_FLAG_VCONN_PWR_MSK); + + return ret; +} + +/** + * @brief Set complete Ctrl register value (Reg 0) + * @param pObj Pointer to component object + * @param pCtrlRegister Pointer on Ctrl register value + * @retval Component status + */ +int32_t TCPP0203_WriteCtrlRegister(TCPP0203_Object_t *pObj, uint8_t *pCtrlRegister) +{ + int32_t ret; + + /* Update value in writing register (reg0) */ + ret = tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, pCtrlRegister, 1); + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) + Reg0_Expected_Value = *pCtrlRegister; +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + + return ret; +} + +/** + * @brief Get complete Ack register value + * @param pObj Pointer to component object + * @param pAckRegister Pointer on Ack register value + * @retval Component status + */ +int32_t TCPP0203_ReadAckRegister(TCPP0203_Object_t *pObj, uint8_t *pAckRegister) +{ + int32_t ret; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, pAckRegister, 1); + + return ret; +} + +/** + * @brief Get complete Flag register value + * @param pObj Pointer to component object + * @param pFlagRegister Pointer on Flag register value + * @retval Component status + */ +int32_t TCPP0203_ReadFlagRegister(TCPP0203_Object_t *pObj, uint8_t *pFlagRegister) +{ + int32_t ret; + + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, pFlagRegister, 1); + + return ret; +} + +/******************** Static functions ****************************************/ +/** + * @brief Wrap TCPP0203 read function to Bus IO function + * @param handle Component object handle + * @param Reg Target register address to read + * @param pData Buffer where Target register value should be stored + * @param Length buffer size to be read + * @retval error status + */ +static int32_t TCPP0203_ReadRegWrap(const void *handle, uint8_t Reg, uint8_t *pData, uint8_t Length) +{ + const TCPP0203_Object_t *pObj = (const TCPP0203_Object_t *)handle; + + return pObj->IO.ReadReg(pObj->IO.Address, Reg, pData, Length); +} + +/** + * @brief Wrap TCPP0203 write function to Bus IO function + * @param handle Component object handle + * @param Reg Target register address to write + * @param pData Target register value to be written + * @param Length Buffer size to be written + * @retval error status + */ +static int32_t TCPP0203_WriteRegWrap(const void *handle, uint8_t Reg, uint8_t *pData, uint8_t Length) +{ + const TCPP0203_Object_t *pObj = (const TCPP0203_Object_t *)handle; + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) + Reg0_Expected_Value = *pData; +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + + return pObj->IO.WriteReg(pObj->IO.Address, Reg, pData, Length); +} + +/** + * @brief TCPP0203 register update function to Bus IO function + * @param handle Component object handle + * @param Reg Target register address to write + * @param pData Target register value to be written + * @param Length Buffer size to be written + * @retval error status + */ +static int32_t TCPP0203_ModifyReg0(TCPP0203_Object_t *pObj, uint8_t Value, uint8_t Mask) +{ + int32_t ret; + uint8_t tmp; + + /* Read current content of ACK register (reflects content of bits set to 1 in Writing register Reg0) */ + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); + + /* Update only the area dedicated to Mask */ + tmp &= ~(Mask); + tmp |= (Value & Mask); + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) + Reg0_Expected_Value = tmp; +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + + /* Update value in writing register (reg0) */ + ret += tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, &tmp, 1); + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) + ret += TCPP0203_CheckReg0Reg1(pObj, Reg0_Expected_Value); +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + + return ret; +} + +#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) +/** + * @brief TCPP0203 register control function between Reg0 and Reg1 value + * @param handle Component object handle + * @param Reg0ExpectedValue Value expected in Reg0 (built after all calls to write functions) + * @retval error status + */ +static int32_t TCPP0203_CheckReg0Reg1(TCPP0203_Object_t *pObj, uint8_t Reg0ExpectedValue) +{ + int32_t ret; + + /* Read current content of ACK register (expected to reflect content of bits set to 1 in Writing register Reg0) */ + ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &Reg1_LastRead_Value, 1); + +#ifdef _TRACE + char str[12]; + sprintf(str, "Exp0_0x%02x", Reg0ExpectedValue); + USBPD_TRACE_Add(USBPD_TRACE_DEBUG, 0U, 0U, (uint8_t *)str, sizeof(str) - 1U); + sprintf(str, "Reg1_0x%02x", Reg1_LastRead_Value); + USBPD_TRACE_Add(USBPD_TRACE_DEBUG, 0U, 0U, (uint8_t *)str, sizeof(str) - 1U); +#endif /* _TRACE */ + + /* Control if Reg1 value is same as Reg0 expected one */ + if (Reg1_LastRead_Value != Reg0ExpectedValue) + { + while (1); + } + + return ret; +} +#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.h b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.h new file mode 100644 index 000000000..271b534fc --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.h @@ -0,0 +1,353 @@ +/** + ****************************************************************************** + * @file tcpp0203.h + * @author MCD Application Team + * @brief This file contains all the functions prototypes for the + * tcpp0203.c driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef TCPP0203_H +#define TCPP0203_H + +/* Includes ------------------------------------------------------------------*/ +#include "tcpp0203_reg.h" +#include + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Component + * @{ + */ + +/** @addtogroup TCPP0203 + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup TCPP0203_Exported_Types TCPP0203 Exported Types + * @{ + */ +typedef int32_t (*TCPP0203_Init_Func)(void); +typedef int32_t (*TCPP0203_DeInit_Func)(void); +typedef int32_t (*TCPP0203_GetTick_Func)(void); +typedef int32_t (*TCPP0203_WriteReg_Func)(uint16_t, uint16_t, uint8_t *, uint16_t); +typedef int32_t (*TCPP0203_ReadReg_Func)(uint16_t, uint16_t, uint8_t *, uint16_t); + +typedef struct +{ + TCPP0203_Init_Func Init; + TCPP0203_DeInit_Func DeInit; + uint16_t Address; + TCPP0203_WriteReg_Func WriteReg; + TCPP0203_ReadReg_Func ReadReg; + TCPP0203_GetTick_Func GetTick; +} TCPP0203_IO_t; + + +typedef struct +{ + TCPP0203_IO_t IO; + TCPP0203_ctx_t Ctx; + uint8_t IsInitialized; +} TCPP0203_Object_t; + +typedef struct +{ + int32_t (*Init)(TCPP0203_Object_t *); + int32_t (*DeInit)(TCPP0203_Object_t *); + int32_t (*Reset)(TCPP0203_Object_t *); + int32_t (*SetVConnSwitch)(TCPP0203_Object_t *, uint8_t); + int32_t (*SetGateDriverProvider)(TCPP0203_Object_t *, uint8_t); + int32_t (*SetGateDriverConsumer)(TCPP0203_Object_t *, uint8_t); + int32_t (*SetPowerMode)(TCPP0203_Object_t *, uint8_t); + int32_t (*SetVBusDischarge)(TCPP0203_Object_t *, uint8_t); + int32_t (*SetVConnDischarge)(TCPP0203_Object_t *, uint8_t); + int32_t (*GetVConnSwitchAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetGateDriverProviderAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetGateDriverConsumerAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetPowerModeAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetVBusDischargeAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetVConnDischargeAck)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetOCPVConnFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetOCPVBusFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetOVPVBusFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetOVPCCFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetOTPFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*GetVBusOkFlag)(TCPP0203_Object_t *, uint8_t *); + int32_t (*ReadTCPPType)(TCPP0203_Object_t *, uint8_t *); + int32_t (*ReadVCONNPower)(TCPP0203_Object_t *, uint8_t *); + int32_t (*WriteCtrlRegister)(TCPP0203_Object_t *, uint8_t *); + int32_t (*ReadAckRegister)(TCPP0203_Object_t *, uint8_t *); + int32_t (*ReadFlagRegister)(TCPP0203_Object_t *, uint8_t *); +} TCPP0203_Drv_t; + +/** + * @} + */ + +/** @defgroup TCPP0203_Exported_Constants TCPP0203 Exported Constants + * @{ + */ +/** + * @brief TCPP0203 Driver Response codes + */ +#define TCPP0203_OK (0) +#define TCPP0203_ERROR (-1) + +/** + * @brief TCPP0203 possible I2C Addresses + */ +#define TCPP0203_I2C_ADDRESS_X68 (0x68U) +#define TCPP0203_I2C_ADDRESS_X6A (0x6AU) + +/** + * @brief TCPP0203 Reg0 Reset Value + */ +#define TCPP0203_REG0_RST_VALUE TCPP0203_GD_CONSUMER_SWITCH_CLOSED + +/** + * @brief TCPP0203 VCONN Switch + */ +#define TCPP0203_VCONN_SWITCH_POS (0U) +#define TCPP0203_VCONN_SWITCH_MSK (0x03U << TCPP0203_VCONN_SWITCH_POS) +#define TCPP0203_VCONN_SWITCH_OPEN (0x00U) +#define TCPP0203_VCONN_SWITCH_CC1 (0x01U << TCPP0203_VCONN_SWITCH_POS) +#define TCPP0203_VCONN_SWITCH_CC2 (0x02U << TCPP0203_VCONN_SWITCH_POS) + +/** + * @brief TCPP0203 Gate Driver Provider values + */ +#define TCPP0203_GD_PROVIDER_SWITCH_POS (2U) +#define TCPP0203_GD_PROVIDER_SWITCH_MSK (0x01U << TCPP0203_GD_PROVIDER_SWITCH_POS) +#define TCPP0203_GD_PROVIDER_SWITCH_OPEN (0x00U) +#define TCPP0203_GD_PROVIDER_SWITCH_CLOSED (TCPP0203_GD_PROVIDER_SWITCH_MSK) + +/** + * @brief TCPP0203 Gate Driver Consumer values + */ +#define TCPP0203_GD_CONSUMER_SWITCH_POS (3U) +#define TCPP0203_GD_CONSUMER_SWITCH_MSK (0x01U << TCPP0203_GD_CONSUMER_SWITCH_POS) +#define TCPP0203_GD_CONSUMER_SWITCH_CLOSED (0x00U) +#define TCPP0203_GD_CONSUMER_SWITCH_OPEN (TCPP0203_GD_CONSUMER_SWITCH_MSK) + +/** + * @brief TCPP0203 Power Mode values + */ +#define TCPP0203_POWER_MODE_POS (4U) +#define TCPP0203_POWER_MODE_MSK (0x03U << TCPP0203_POWER_MODE_POS) +#define TCPP0203_POWER_MODE_HIBERNATE (0x00U) +#define TCPP0203_POWER_MODE_LOWPOWER (0x02U << TCPP0203_POWER_MODE_POS) +#define TCPP0203_POWER_MODE_NORMAL (0x01U << TCPP0203_POWER_MODE_POS) + +/** + * @brief TCPP0203 VBUS Discharge management + */ +#define TCPP0203_VBUS_DISCHARGE_POS (6U) +#define TCPP0203_VBUS_DISCHARGE_MSK (0x01U << TCPP0203_VBUS_DISCHARGE_POS) +#define TCPP0203_VBUS_DISCHARGE_OFF (0x00U) +#define TCPP0203_VBUS_DISCHARGE_ON (TCPP0203_VBUS_DISCHARGE_MSK) + +/** + * @brief TCPP0203 VConn Discharge management + */ +#define TCPP0203_VCONN_DISCHARGE_POS (7U) +#define TCPP0203_VCONN_DISCHARGE_MSK (0x01U << TCPP0203_VCONN_DISCHARGE_POS) +#define TCPP0203_VCONN_DISCHARGE_OFF (0x00U) +#define TCPP0203_VCONN_DISCHARGE_ON (TCPP0203_VCONN_DISCHARGE_MSK) + +/** + * @brief TCPP0203 VCONN Switch Acknowledge + */ +#define TCPP0203_VCONN_SWITCH_ACK_POS (0U) +#define TCPP0203_VCONN_SWITCH_ACK_MSK (0x03U << TCPP0203_VCONN_SWITCH_ACK_POS) +#define TCPP0203_VCONN_SWITCH_ACK_OPEN (0x00U) +#define TCPP0203_VCONN_SWITCH_ACK_CC1 (0x02U << TCPP0203_VCONN_SWITCH_ACK_POS) +#define TCPP0203_VCONN_SWITCH_ACK_CC2 (0x01U << TCPP0203_VCONN_SWITCH_ACK_POS) + +/** + * @brief TCPP0203 Gate Driver Provider Acknowledge + */ +#define TCPP0203_GD_PROVIDER_SWITCH_ACK_POS (2U) +#define TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK (0x01U << TCPP0203_GD_PROVIDER_SWITCH_ACK_POS) +#define TCPP0203_GD_PROVIDER_SWITCH_ACK_OPEN (0x00U) +#define TCPP0203_GD_PROVIDER_SWITCH_ACK_CLOSED (TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK) + +/** + * @brief TCPP0203 Gate Driver Consumer Acknowledge + */ +#define TCPP0203_GD_CONSUMER_SWITCH_ACK_POS (3U) +#define TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK (0x01U << TCPP0203_GD_CONSUMER_SWITCH_ACK_POS) +#define TCPP0203_GD_CONSUMER_SWITCH_ACK_CLOSED (0x00U) +#define TCPP0203_GD_CONSUMER_SWITCH_ACK_OPEN (TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK) + +/** + * @brief TCPP0203 Power Mode Acknowledge + */ +#define TCPP0203_POWER_MODE_ACK_POS (4U) +#define TCPP0203_POWER_MODE_ACK_MSK (0x03U << TCPP0203_POWER_MODE_ACK_POS) +#define TCPP0203_POWER_MODE_ACK_HIBERNATE (0x00U) +#define TCPP0203_POWER_MODE_ACK_LOWPOWER (0x01U << TCPP0203_POWER_MODE_ACK_POS) +#define TCPP0203_POWER_MODE_ACK_NORMAL (0x02U << TCPP0203_POWER_MODE_ACK_POS) + +/** + * @brief TCPP0203 VBUS Discharge Acknowledge + */ +#define TCPP0203_VBUS_DISCHARGE_ACK_POS (6U) +#define TCPP0203_VBUS_DISCHARGE_ACK_MSK (0x01U << TCPP0203_VBUS_DISCHARGE_ACK_POS) +#define TCPP0203_VBUS_DISCHARGE_ACK_OFF (0x00U) +#define TCPP0203_VBUS_DISCHARGE_ACK_ON (TCPP0203_VBUS_DISCHARGE_ACK_MSK) + +/** + * @brief TCPP0203 VConn Discharge Acknowledge + */ +#define TCPP0203_VCONN_DISCHARGE_ACK_POS (7U) +#define TCPP0203_VCONN_DISCHARGE_ACK_MSK (0x01U << TCPP0203_VCONN_DISCHARGE_ACK_POS) +#define TCPP0203_VCONN_DISCHARGE_ACK_OFF (0x00U) +#define TCPP0203_VCONN_DISCHARGE_ACK_ON (TCPP0203_VCONN_DISCHARGE_ACK_MSK) + +/** + * @brief TCPP0203 OCP Vconn Flag management + */ +#define TCPP0203_FLAG_OCP_VCONN_POS (0U) +#define TCPP0203_FLAG_OCP_VCONN_MSK (0x01U << TCPP0203_FLAG_OCP_VCONN_POS) +#define TCPP0203_FLAG_OCP_VCONN_SET (TCPP0203_FLAG_OCP_VCONN_MSK) +#define TCPP0203_FLAG_OCP_VCONN_RESET (0x00U) + +/** + * @brief TCPP0203 OCP VBUS Flag management + */ +#define TCPP0203_FLAG_OCP_VBUS_POS (1U) +#define TCPP0203_FLAG_OCP_VBUS_MSK (0x01U << TCPP0203_FLAG_OCP_VBUS_POS) +#define TCPP0203_FLAG_OCP_VBUS_SET (TCPP0203_FLAG_OCP_VBUS_MSK) +#define TCPP0203_FLAG_OCP_VBUS_RESET (0x00U) + +/** + * @brief TCPP0203 OVP VBUS Flag management + */ +#define TCPP0203_FLAG_OVP_VBUS_POS (2U) +#define TCPP0203_FLAG_OVP_VBUS_MSK (0x01U << TCPP0203_FLAG_OVP_VBUS_POS) +#define TCPP0203_FLAG_OVP_VBUS_SET (TCPP0203_FLAG_OVP_VBUS_MSK) +#define TCPP0203_FLAG_OVP_VBUS_RESET (0x00U) + +/** + * @brief TCPP0203 OVP CC Flag management + */ +#define TCPP0203_FLAG_OVP_CC_POS (3U) +#define TCPP0203_FLAG_OVP_CC_MSK (0x01U << TCPP0203_FLAG_OVP_CC_POS) +#define TCPP0203_FLAG_OVP_CC_SET (TCPP0203_FLAG_OVP_CC_MSK) +#define TCPP0203_FLAG_OVP_CC_RESET (0x00U) + +/** + * @brief TCPP0203 OTP Flag management + */ +#define TCPP0203_FLAG_OTP_POS (4U) +#define TCPP0203_FLAG_OTP_MSK (0x01U << TCPP0203_FLAG_OTP_POS) +#define TCPP0203_FLAG_OTP_SET (TCPP0203_FLAG_OTP_MSK) +#define TCPP0203_FLAG_OTP_RESET (0x00U) + +/** + * @brief TCPP0203 VBUS OK Flag management + */ +#define TCPP0203_FLAG_VBUS_OK_POS (5U) +#define TCPP0203_FLAG_VBUS_OK_MSK (0x01U << TCPP0203_FLAG_VBUS_OK_POS) +#define TCPP0203_FLAG_VBUS_OK_SET (TCPP0203_FLAG_VBUS_OK_MSK) +#define TCPP0203_FLAG_VBUS_OK_RESET (0x00U) + +/** + * @brief TCPP0203 VConn Power + */ +#define TCPP0203_FLAG_VCONN_PWR_POS (6U) +#define TCPP0203_FLAG_VCONN_PWR_MSK (0x01U << TCPP0203_FLAG_VCONN_PWR_POS) +#define TCPP0203_FLAG_VCONN_PWR_1W (TCPP0203_FLAG_VCONN_PWR_MSK) +#define TCPP0203_FLAG_VCONN_PWR_0_1W (0x00U) + +/** + * @brief TCPP0203 Device Type + */ +#define TCPP0203_DEVICE_TYPE_POS (7U) +#define TCPP0203_DEVICE_TYPE_MSK (0x01U << TCPP0203_DEVICE_TYPE_POS) +#define TCPP0203_DEVICE_TYPE_02 (TCPP0203_DEVICE_TYPE_MSK) +#define TCPP0203_DEVICE_TYPE_03 (0x00U) + +/** + * @} + */ + +/** @defgroup TCPP0203_Exported_Macros TCPP0203 Exported Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup TCPP0203_Exported_Functions TCPP0203 Exported Functions + * @{ + */ + +/*------------------------------------------------------------------------------ + TCPP02/03 Type-C port protection functions +------------------------------------------------------------------------------*/ +/* High Layer codec functions */ +int32_t TCPP0203_RegisterBusIO(TCPP0203_Object_t *pObj, TCPP0203_IO_t *pIO); +int32_t TCPP0203_Init(TCPP0203_Object_t *pObj); +int32_t TCPP0203_DeInit(TCPP0203_Object_t *pObj); +int32_t TCPP0203_Reset(TCPP0203_Object_t *pObj); +int32_t TCPP0203_SetVConnSwitch(TCPP0203_Object_t *pObj, uint8_t VConnSwitch); +int32_t TCPP0203_SetGateDriverProvider(TCPP0203_Object_t *pObj, uint8_t GateDriverProvider); +int32_t TCPP0203_SetGateDriverConsumer(TCPP0203_Object_t *pObj, uint8_t GateDriverConsumer); +int32_t TCPP0203_SetPowerMode(TCPP0203_Object_t *pObj, uint8_t PowerMode); +int32_t TCPP0203_SetVBusDischarge(TCPP0203_Object_t *pObj, uint8_t VBusDischarge); +int32_t TCPP0203_SetVConnDischarge(TCPP0203_Object_t *pObj, uint8_t VConnDischarge); +int32_t TCPP0203_GetVConnSwitchAck(TCPP0203_Object_t *pObj, uint8_t *pVConnSwitchAck); +int32_t TCPP0203_GetGateDriverProviderAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverProviderAck); +int32_t TCPP0203_GetGateDriverConsumerAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverConsumerAck); +int32_t TCPP0203_GetPowerModeAck(TCPP0203_Object_t *pObj, uint8_t *pPowerModeAck); +int32_t TCPP0203_GetVBusDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVBusDischargeAck); +int32_t TCPP0203_GetVConnDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVConnDischargeAck); +int32_t TCPP0203_GetOCPVConnFlag(TCPP0203_Object_t *pObj, uint8_t *pOCPVConnFlag); +int32_t TCPP0203_GetOCPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pGetOCPVBusFlag); +int32_t TCPP0203_GetOVPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPVBusFlag); +int32_t TCPP0203_GetOVPCCFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPCCFlag); +int32_t TCPP0203_GetOTPFlag(TCPP0203_Object_t *pObj, uint8_t *pOTPFlag); +int32_t TCPP0203_GetVBusOkFlag(TCPP0203_Object_t *pObj, uint8_t *pVBusOkFlag); +int32_t TCPP0203_ReadTCPPType(TCPP0203_Object_t *pObj, uint8_t *pTCPPType); +int32_t TCPP0203_ReadVCONNPower(TCPP0203_Object_t *pObj, uint8_t *pVCONNPower); +int32_t TCPP0203_WriteCtrlRegister(TCPP0203_Object_t *pObj, uint8_t *pCtrlRegister); +int32_t TCPP0203_ReadAckRegister(TCPP0203_Object_t *pObj, uint8_t *pAckRegister); +int32_t TCPP0203_ReadFlagRegister(TCPP0203_Object_t *pObj, uint8_t *pFlagRegister); + +/** + * @} + */ + +/* TCPP02/03 Type-C port protection driver structure */ +extern TCPP0203_Drv_t TCPP0203_Driver; + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* TCPP0203_H */ diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.c b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.c new file mode 100644 index 000000000..8025fa85e --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.c @@ -0,0 +1,73 @@ +/** + ****************************************************************************** + * @file tcpp0203_reg.c + * @author MCD Application Team + * @brief This file provides unitary register function to control the TCPP02-03 + * Type-C port protection driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "tcpp0203_reg.h" + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Components + * @{ + */ + +/** @addtogroup TCPP0203 + * @brief This file provides a set of functions needed to drive the + * TCPP02/03 Type-C port protection codec. + * @{ + */ + +/************** Generic Function *******************/ +/******************************************************************************* + * Function Name : tcpp0203_read_reg + * Description : Generic Reading function. It must be fulfilled with either + * I2C or SPI reading functions + * Input : Register Address, length of buffer + * Output : data Read + *******************************************************************************/ +int32_t tcpp0203_read_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length) +{ + return ctx->ReadReg(ctx->handle, reg, data, length); +} + +/******************************************************************************* + * Function Name : tcpp0203_write_reg + * Description : Generic Writing function. It must be fulfilled with either + * I2C or SPI writing function + * Input : Register Address, data to be written, length of buffer + * Output : None + *******************************************************************************/ +int32_t tcpp0203_write_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length) +{ + return ctx->WriteReg(ctx->handle, reg, data, length); +} + +/******************************************************************************/ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.h b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.h new file mode 100644 index 000000000..92420e1fe --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.h @@ -0,0 +1,98 @@ +/** + ****************************************************************************** + * @file tcpp0203_reg.h + * @author MCD Application Team + * @brief Header of tcpp0203_reg.c + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2021 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef TCPP0203_REG_H +#define TCPP0203_REG_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Component + * @{ + */ + +/** @addtogroup TCPP0203 + * @{ + */ + + +/** @defgroup TCPP0203_Exported_Constants TCPP0203 Exported Constants + * @{ + */ +/******************************************************************************/ +/****************************** REGISTER MAPPING ******************************/ +/******************************************************************************/ +#define TCPP0203_WRITE_REG 0x00U +#define TCPP0203_PROG_CTRL TCPP0203_WRITE_REG +#define TCPP0203_READ_REG1 0x01U +#define TCPP0203_ACK_REG TCPP0203_READ_REG1 +#define TCPP0203_READ_REG2 0x02U +#define TCPP0203_FLAG_REG TCPP0203_READ_REG2 + +/** + * @} + */ + +/************** Generic Function *******************/ + +typedef int32_t (*TCPP0203_Write_Func)(const void *, uint8_t, uint8_t *, uint8_t); +typedef int32_t (*TCPP0203_Read_Func)(const void *, uint8_t, uint8_t *, uint8_t); + +typedef struct +{ + TCPP0203_Write_Func WriteReg; + TCPP0203_Read_Func ReadReg; + void *handle; +} TCPP0203_ctx_t; + +/******************************************************************************* + * Register : Generic - All + * Address : Generic - All + * Bit Group Name: None + * Permission : W + *******************************************************************************/ +int32_t tcpp0203_write_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length); +int32_t tcpp0203_read_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length); + +#ifdef __cplusplus +} +#endif + +#endif /* TCPP0203_REG_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/hw/bsp/stm32n6/family.c b/hw/bsp/stm32n6/family.c new file mode 100644 index 000000000..0ec1875ac --- /dev/null +++ b/hw/bsp/stm32n6/family.c @@ -0,0 +1,276 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 + * William D. Jones (thor0505@comcast.net), + * Ha Thach (tinyusb.org) + * Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + manufacturer: STMicroelectronics +*/ + +// Suppress warning caused by mcu driver +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" +#endif + +#include "stm32n6xx_hal.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +#include "bsp/board_api.h" + +TU_ATTR_UNUSED static void Error_Handler(void) { } + +void HardFault_Handler(void); + +typedef struct { + GPIO_TypeDef* port; + GPIO_InitTypeDef pin_init; + uint8_t active_state; +} board_pindef_t; + +#include "board.h" + +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ + +#ifdef UART_DEV +UART_HandleTypeDef UartHandle = { + .Instance = UART_DEV, + .Init = { + .BaudRate = CFG_BOARD_UART_BAUDRATE, + .WordLength = UART_WORDLENGTH_8B, + .StopBits = UART_STOPBITS_1, + .Parity = UART_PARITY_NONE, + .HwFlowCtl = UART_HWCONTROL_NONE, + .Mode = UART_MODE_TX_RX, + .OverSampling = UART_OVERSAMPLING_16, + } +}; +#endif + +#ifndef SWO_FREQ +#define SWO_FREQ 4000000 +#endif + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ + +// Despite being call USB2_OTG_FS on some MCUs +// OTG_FS is marked as RHPort0 by TinyUSB to be consistent across stm32 port +void USB2_OTG_HS_IRQHandler(void) { + tusb_int_handler(0, true); +} + +// Despite being call USB1_OTG_HS on some MCUs +// OTG_HS is marked as RHPort1 by TinyUSB to be consistent across stm32 port +void USB1_OTG_HS_IRQHandler(void) { + tusb_int_handler(1, true); +} + +void board_init(void) { + + /* Enable BusFault and SecureFault handlers (HardFault is default) */ + SCB->SHCSR |= (SCB_SHCSR_BUSFAULTENA_Msk | SCB_SHCSR_SECUREFAULTENA_Msk); + + HAL_PWREx_EnableVddA(); + HAL_PWREx_EnableVddIO2(); + HAL_PWREx_EnableVddIO3(); + HAL_PWREx_EnableVddIO4(); + HAL_PWREx_EnableVddIO5(); + + HAL_Init(); + + // Implemented in board.h + SystemClock_Config(); + + // Enable All GPIOs clocks + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPION_CLK_ENABLE(); + __HAL_RCC_GPIOO_CLK_ENABLE(); + __HAL_RCC_GPIOP_CLK_ENABLE(); + __HAL_RCC_GPIOQ_CLK_ENABLE(); + + // HAL_ICACHE_Enable(); + + for (uint8_t i = 0; i < TU_ARRAY_SIZE(board_pindef); i++) { + HAL_GPIO_Init(board_pindef[i].port, &board_pindef[i].pin_init); + } + + NVIC_SetPriority(UCPD1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),5, 0)); + NVIC_EnableIRQ(UCPD1_IRQn); + +#if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); + +#elif CFG_TUSB_OS == OPT_OS_FREERTOS + // Explicitly disable systick to prevent its ISR runs before scheduler start + SysTick->CTRL &= ~1U; + + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + + NVIC_SetPriority(OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); +#endif + + + +#ifdef UART_DEV + UART_CLK_EN(); + HAL_UART_Init(&UartHandle); +#endif + + + __HAL_RCC_USB1_OTG_HS_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + HAL_PWREx_EnableVddUSBVMEN(); + while(__HAL_PWR_GET_FLAG(PWR_FLAG_USB33RDY)); + HAL_PWREx_EnableVddUSB(); + + LL_AHB5_GRP1_ForceReset(0x00800000); + __HAL_RCC_USB1_OTG_HS_FORCE_RESET(); + __HAL_RCC_USB1_OTG_HS_PHY_FORCE_RESET(); + + LL_RCC_HSE_SelectHSEDiv2AsDiv2Clock(); + LL_AHB5_GRP1_ReleaseReset(0x00800000); + + /* Peripheral clock enable */ + __HAL_RCC_USB1_OTG_HS_CLK_ENABLE(); + + /* Required few clock cycles before accessing USB PHY Controller Registers */ + HAL_Delay(1); + + USB1_HS_PHYC->USBPHYC_CR &= ~(0x7 << 0x4); + + USB1_HS_PHYC->USBPHYC_CR |= (0x1 << 16) | + (0x2 << 4) | + (0x1 << 2) | + 0x1U; + + __HAL_RCC_USB1_OTG_HS_PHY_RELEASE_RESET(); + + /* Required few clock cycles before Releasing Reset */ + HAL_Delay(1); + + __HAL_RCC_USB1_OTG_HS_RELEASE_RESET(); + + /* Peripheral PHY clock enable */ + __HAL_RCC_USB1_OTG_HS_PHY_CLK_ENABLE(); + + board_init2(); + +#if CFG_TUH_ENABLED + board_vbus_set(BOARD_TUH_RHPORT, 1); +#endif +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +void board_led_write(bool state) { +#ifdef PINID_LED + board_pindef_t* pindef = &board_pindef[PINID_LED]; + GPIO_PinState pin_state = state == pindef->active_state ? GPIO_PIN_SET : GPIO_PIN_RESET; + HAL_GPIO_WritePin(pindef->port, pindef->pin_init.Pin, pin_state); +#else + (void) state; +#endif +} + +uint32_t board_button_read(void) { +#ifdef PINID_BUTTON + board_pindef_t* pindef = &board_pindef[PINID_BUTTON]; + return pindef->active_state == HAL_GPIO_ReadPin(pindef->port, pindef->pin_init.Pin); +#else + return 0; +#endif +} + +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; + uint32_t* id32 = (uint32_t*) (uintptr_t) id; + uint8_t const len = 12; + + 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) { +#ifdef UART_DEV + HAL_UART_Transmit(&UartHandle, (uint8_t * )(uintptr_t) + buf, len, 0xffff); + return len; +#else + (void) buf; (void) len; + return -1; +#endif +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; + +void SysTick_Handler(void) { + HAL_IncTick(); + system_ticks++; +} + +uint32_t board_millis(void) { + return system_ticks; +} + +#endif + +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) { +} diff --git a/hw/bsp/stm32n6/family.cmake b/hw/bsp/stm32n6/family.cmake new file mode 100644 index 000000000..600af7cdb --- /dev/null +++ b/hw/bsp/stm32n6/family.cmake @@ -0,0 +1,147 @@ +include_guard() + +set(ST_FAMILY n6) +set(ST_PREFIX stm32${ST_FAMILY}xx) + +set(ST_HAL_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver) +set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis_device_${ST_FAMILY}) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m55 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS STM32N6 CACHE INTERNAL "") + +# ---------------------- +# Port & Speed Selection +# ---------------------- +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 1) +endif () +if (NOT DEFINED RHPORT_HOST) + set(RHPORT_HOST 1) +endif () + +if (NOT DEFINED RHPORT_SPEED) + set(RHPORT_SPEED OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED) +endif () +if (NOT DEFINED RHPORT_DEVICE_SPEED) + list(GET RHPORT_SPEED ${RHPORT_DEVICE} RHPORT_DEVICE_SPEED) +endif () +if (NOT DEFINED RHPORT_HOST_SPEED) + list(GET RHPORT_SPEED ${RHPORT_HOST} RHPORT_HOST_SPEED) +endif () + +cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif() + + # Startup & Linker script + set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) + + if(NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_flash.ld) + endif() + set(LD_FILE_Clang ${LD_FILE_GNU}) + if(NOT DEFINED LD_FILE_IAR) + set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) + endif() + + add_library(${BOARD_TARGET} STATIC + ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}_ns.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_dma.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_i2c.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMSIS_5}/CMSIS/Core/Include + ${ST_CMSIS}/Include + ${ST_HAL_DRIVER}/Inc + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + BOARD_TUD_RHPORT=${RHPORT_DEVICE} + BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} + BOARD_TUH_RHPORT=${RHPORT_HOST} + BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_STM32N6 ${RTOS}) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_stlink(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/stm32n6/family.mk b/hw/bsp/stm32n6/family.mk new file mode 100644 index 000000000..97930e189 --- /dev/null +++ b/hw/bsp/stm32n6/family.mk @@ -0,0 +1,101 @@ +ST_FAMILY = n6 +ST_PREFIX = stm32${ST_FAMILY}xx +ST_PREFIX_LONG = stm32${ST_FAMILY}57xx +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/${ST_PREFIX}_hal_driver + +UF2_FAMILY_ID = 0x6db66083 + +include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= cortex-m55 + +# ---------------------- +# Port & Speed Selection +# ---------------------- +RHPORT_SPEED ?= OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED +RHPORT_DEVICE ?= 1 +RHPORT_HOST ?= 1 + +# Determine RHPORT_DEVICE_SPEED if not defined +ifndef RHPORT_DEVICE_SPEED +ifeq ($(RHPORT_DEVICE), 0) + RHPORT_DEVICE_SPEED = $(firstword $(RHPORT_SPEED)) +else + RHPORT_DEVICE_SPEED = $(lastword $(RHPORT_SPEED)) +endif +endif + +# Determine RHPORT_HOST_SPEED if not defined +ifndef RHPORT_HOST_SPEED +ifeq ($(RHPORT_HOST), 0) + RHPORT_HOST_SPEED = $(firstword $(RHPORT_SPEED)) +else + RHPORT_HOST_SPEED = $(lastword $(RHPORT_SPEED)) +endif +endif + +# -------------- +# Compiler Flags +# -------------- +CFLAGS += \ + -DCFG_TUSB_MCU=OPT_MCU_STM32N6 \ + -DBOARD_TUD_RHPORT=${RHPORT_DEVICE} \ + -DBOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} \ + -DBOARD_TUH_RHPORT=${RHPORT_HOST} \ + -DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} + +# GCC Flags +CFLAGS_GCC += \ + -flto \ + +# suppress warning caused by vendor mcu driver +CFLAGS_GCC += \ + -Wno-error=cast-align \ + -Wno-error=unused-parameter \ + +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + --specs=nosys.specs --specs=nano.specs + +# ----------------- +# Sources & Include +# ----------------- + +SRC_C += \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ + src/portable/synopsys/dwc2/hcd_dwc2.c \ + src/portable/synopsys/dwc2/dwc2_common.c \ + $(ST_CMSIS)/Source/Templates/system_${ST_PREFIX}_fsbl.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_dma.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_hcd.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_i2c.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pcd.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pcd_ex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pwr.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pwr_ex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_rif.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_uart_ex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_ll_usb.c \ + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc + +# Linker +LD_FILE_GCC = $(BOARD_PATH)/STM32N657XX_AXISRAM2_fsbl.ld + +# Startup +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_$(ST_PREFIX_LONG)_fsbl.s +SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT).s + +# Linker +LD_FILE_GCC ?= $(ST_CMSIS)/Source/Templates/gcc/linker/$(ST_PREFIX_LONG)_flash.ld +LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash.icf diff --git a/hw/bsp/stm32n6/partition_stm32n657xx.h b/hw/bsp/stm32n6/partition_stm32n657xx.h new file mode 100644 index 000000000..713068609 --- /dev/null +++ b/hw/bsp/stm32n6/partition_stm32n657xx.h @@ -0,0 +1,792 @@ +/** + ****************************************************************************** + * @file partition_stm32n657xx.h + * @author MCD Application Team + * @brief CMSIS STM32N657xx Device Initial Setup for Secure / Non-Secure Zones + * for ARMCM55 based on CMSIS CORE V5.3.1 partition_ARMCM33.h Template. + * + * This file contains: + * - Initialize Security Attribution Unit (SAU) CTRL register + * - Setup behavior of Sleep and Exception Handling + * - Setup behavior of Floating Point Unit + * - Setup Interrupt Target + * + ******************************************************************************/ +/* + * Copyright (c) 2009-2016 ARM Limited. All rights reserved. + * Portions Copyright (c) 2023 STMicroelectronics, all rights reserved + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PARTITION_STM32N657XX_H +#define PARTITION_STM32N657XX_H + +/* +//-------- <<< Use Configuration Wizard in Context Menu >>> ----------------- +*/ + +/* +// Initialize Security Attribution Unit (SAU) CTRL register +*/ +#define SAU_INIT_CTRL 0 + +/* +// Enable SAU +// Value for SAU->CTRL register bit ENABLE +*/ +#define SAU_INIT_CTRL_ENABLE 0 + +/* +// When SAU is disabled +// <0=> All Memory is Secure +// <1=> All Memory is Non-Secure +// Value for SAU->CTRL register bit ALLNS +// When all Memory is Non-Secure (ALLNS is 1), IDAU can override memory map configuration. +*/ +#define SAU_INIT_CTRL_ALLNS 0 + +/* +// +*/ + +/* +// Initialize Security Attribution Unit (SAU) Address Regions +// SAU configuration specifies regions to be one of: +// - Secure and Non-Secure Callable +// - Non-Secure +// Note: All memory regions not configured by SAU are Secure +*/ +#define SAU_REGIONS_MAX 8 /* Max. number of SAU regions */ + +/* +// Initialize SAU Region 0 +// Setup SAU Region 0 memory attributes +*/ +#define SAU_INIT_REGION0 0 + +/* +// Start Address <0-0xFFFFFFE0> +*/ +#define SAU_INIT_START0 0x00000000 /* start address of SAU region 0 */ + +/* +// End Address <0x1F-0xFFFFFFFF> +*/ +#define SAU_INIT_END0 0x00000000 /* end address of SAU region 0 */ + +/* +// Region is +// <0=>Non-Secure +// <1=>Secure, Non-Secure Callable +*/ +#define SAU_INIT_NSC0 0 +/* +// +*/ + +/* +// Initialize SAU Region 1 +// Setup SAU Region 1 memory attributes +*/ +#define SAU_INIT_REGION1 0 + +/* +// Start Address <0-0xFFFFFFE0> +*/ +#define SAU_INIT_START1 0x00000000 /* start address of SAU region 1 */ + +/* +// End Address <0x1F-0xFFFFFFFF> +*/ +#define SAU_INIT_END1 0x00000000 /* end address of SAU region 1 */ + +/* +// Region is +// <0=>Non-Secure +// <1=>Secure, Non-Secure Callable +*/ +#define SAU_INIT_NSC1 0 +/* +// +*/ + +/* +// Initialize SAU Region 2 +// Setup SAU Region 2 memory attributes +*/ +#define SAU_INIT_REGION2 0 + +/* +// Start Address <0-0xFFFFFFE0> +*/ +#define SAU_INIT_START2 0x00000000 /* start address of SAU region 2 */ + +/* +// End Address <0x1F-0xFFFFFFFF> +*/ +#define SAU_INIT_END2 0x00000000 /* end address of SAU region 2 */ + +/* +// Region is +// <0=>Non-Secure +// <1=>Secure, Non-Secure Callable +*/ +#define SAU_INIT_NSC2 0 +/* +// +*/ + +/* +// Initialize SAU Region 3 +// Setup SAU Region 3 memory attributes +*/ +#define SAU_INIT_REGION3 0 + +/* +// Start Address <0-0xFFFFFFE0> +*/ +#define SAU_INIT_START3 0x00000000 /* start address of SAU region 3 */ + +/* +// End Address <0x1F-0xFFFFFFFF> +*/ +#define SAU_INIT_END3 0x00000000 /* end address of SAU region 3 */ + +/* +// Region is +// <0=>Non-Secure +// <1=>Secure, Non-Secure Callable +*/ +#define SAU_INIT_NSC3 0 +/* +// +*/ + +/* +// Initialize SAU Region 4 +// Setup SAU Region 4 memory attributes +*/ +#define SAU_INIT_REGION4 0 + +/* +// Start Address <0-0xFFFFFFE0> +*/ +#define SAU_INIT_START4 0x00000000 /* start address of SAU region 4 */ + +/* +// End Address <0x1F-0xFFFFFFFF> +*/ +#define SAU_INIT_END4 0x00000000 /* end address of SAU region 4 */ + +/* +// Region is +// <0=>Non-Secure +// <1=>Secure, Non-Secure Callable +*/ +#define SAU_INIT_NSC4 0 +/* +// +*/ + +/* +// Initialize SAU Region 5 +// Setup SAU Region 5 memory attributes +*/ +#define SAU_INIT_REGION5 0 + +/* +// Start Address <0-0xFFFFFFE0> +*/ +#define SAU_INIT_START5 0x00000000 /* start address of SAU region 5 */ + +/* +// End Address <0x1F-0xFFFFFFFF> +*/ +#define SAU_INIT_END5 0x00000000 /* end address of SAU region 5 */ + +/* +// Region is +// <0=>Non-Secure +// <1=>Secure, Non-Secure Callable +*/ +#define SAU_INIT_NSC5 0 +/* +// +*/ + +/* +// Initialize SAU Region 6 +// Setup SAU Region 6 memory attributes +*/ +#define SAU_INIT_REGION6 0 + +/* +// Start Address <0-0xFFFFFFE0> +*/ +#define SAU_INIT_START6 0x00000000 /* start address of SAU region 6 */ + +/* +// End Address <0x1F-0xFFFFFFFF> +*/ +#define SAU_INIT_END6 0x00000000 /* end address of SAU region 6 */ + +/* +// Region is +// <0=>Non-Secure +// <1=>Secure, Non-Secure Callable +*/ +#define SAU_INIT_NSC6 0 +/* +// +*/ + +/* +// Initialize SAU Region 7 +// Setup SAU Region 7 memory attributes +*/ +#define SAU_INIT_REGION7 0 + +/* +// Start Address <0-0xFFFFFFE0> +*/ +#define SAU_INIT_START7 0x00000000 /* start address of SAU region 7 */ + +/* +// End Address <0x1F-0xFFFFFFFF> +*/ +#define SAU_INIT_END7 0x00000000 /* end address of SAU region 7 */ + +/* +// Region is +// <0=>Non-Secure +// <1=>Secure, Non-Secure Callable +*/ +#define SAU_INIT_NSC7 0 +/* +// +*/ + +/* +// +*/ + +/* +// Setup behaviour of Sleep and Exception Handling +*/ +#define SCB_CSR_AIRCR_INIT 0 + +/* +// Deep Sleep can be enabled by +// <0=>Secure and Non-Secure state +// <1=>Secure state only +// Value for SCB->CSR register bit DEEPSLEEPS +*/ +#define SCB_CSR_DEEPSLEEPS_VAL 0 + +/* +// System reset request accessible from +// <0=> Secure and Non-Secure state +// <1=> Secure state only +// Value for SCB->AIRCR register bit SYSRESETREQS +*/ +#define SCB_AIRCR_SYSRESETREQS_VAL 0 + +/* +// Priority of Non-Secure exceptions is +// <0=> Not altered +// <1=> Lowered to 0x04-0x07 +// Value for SCB->AIRCR register bit PRIS +*/ +#define SCB_AIRCR_PRIS_VAL 0 + +/* +// BusFault, HardFault, and NMI target +// <0=> Secure state +// <1=> Non-Secure state +// Value for SCB->AIRCR register bit BFHFNMINS +*/ +#define SCB_AIRCR_BFHFNMINS_VAL 0 + +/* +// +*/ + +/* +// Setup behaviour of Floating Point Unit +*/ +#define TZ_FPU_NS_USAGE 1 + +/* +// Floating Point Unit usage +// <0=> Secure state only +// <3=> Secure and Non-Secure state +// Value for SCB->NSACR register bits CP10, CP11 +*/ +#define SCB_NSACR_CP10_11_VAL 3 + +/* +// Treat floating-point registers as Secure +// <0=> Disabled +// <1=> Enabled +// Value for FPU->FPCCR register bit TS +*/ +#define FPU_FPCCR_TS_VAL 0 + +/* +// Clear on return (CLRONRET) accessibility +// <0=> Secure and Non-Secure state +// <1=> Secure state only +// Value for FPU->FPCCR register bit CLRONRETS +*/ +#define FPU_FPCCR_CLRONRETS_VAL 0 + +/* +// Clear floating-point caller saved registers on exception return +// <0=> Disabled +// <1=> Enabled +// Value for FPU->FPCCR register bit CLRONRET +*/ +#define FPU_FPCCR_CLRONRET_VAL 1 + +/* +// +*/ + +/* +// Setup Interrupt Target +*/ + +/* +// Initialize ITNS 0 (Interrupts 0..31) +*/ +#define NVIC_INIT_ITNS0 1 + +/* +// Interrupts 0..31 +// PVD_IRQn <0=> Secure state <1=> Non-Secure state +// Reserved <0=> Secure state <1=> Non-Secure state +// DTS_IRQn <0=> Secure state <1=> Non-Secure state +// RCC_IRQn <0=> Secure state <1=> Non-Secure state +// LOCKUP_IRQn <0=> Secure state <1=> Non-Secure state +// CACHE_ECC_IRQn <0=> Secure state <1=> Non-Secure state +// TCM_ECC_IRQn <0=> Secure state <1=> Non-Secure state +// BKP_ECC_IRQn <0=> Secure state <1=> Non-Secure state +// FPU_IRQn <0=> Secure state <1=> Non-Secure state +// Reserved <0=> Secure state <1=> Non-Secure state +// RTC_S_IRQn <0=> Secure state <1=> Non-Secure state +// TAMP_IRQn <0=> Secure state <1=> Non-Secure state +// RIFSC_TAMPER_IRQn <0=> Secure state <1=> Non-Secure state +// IAC_IRQn <0=> Secure state <1=> Non-Secure state +// RCC_S_IRQn <0=> Secure state <1=> Non-Secure state +// Reserved <0=> Secure state <1=> Non-Secure state +// RTC_IRQn <0=> Secure state <1=> Non-Secure state +// Reserved <0=> Secure state <1=> Non-Secure state +// IWDG_IRQn <0=> Secure state <1=> Non-Secure state +// WWDG_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI0_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI1_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI2_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI3_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI4_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI5_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI6_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI7_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI8_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI9_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI10_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI11_IRQn <0=> Secure state <1=> Non-Secure state +*/ +#define NVIC_INIT_ITNS0_VAL 0x00000000 + +/* +// +*/ + +/* +// Initialize ITNS 1 (Interrupts 32..63) +*/ +#define NVIC_INIT_ITNS1 1 + +/* +// Interrupts 32..63 +// EXTI12_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI13_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI14_IRQn <0=> Secure state <1=> Non-Secure state +// EXTI15_IRQn <0=> Secure state <1=> Non-Secure state +// SAES_IRQn <0=> Secure state <1=> Non-Secure state +// CRYP_IRQn <0=> Secure state <1=> Non-Secure state +// PKA_IRQn <0=> Secure state <1=> Non-Secure state +// HASH_IRQn <0=> Secure state <1=> Non-Secure state +// RNG_IRQn <0=> Secure state <1=> Non-Secure state +// Reserved <0=> Secure state <1=> Non-Secure state +// MCE1_IRQn <0=> Secure state <1=> Non-Secure state +// MCE2_IRQn <0=> Secure state <1=> Non-Secure state +// MCE3_IRQn <0=> Secure state <1=> Non-Secure state +// MCE4_IRQn <0=> Secure state <1=> Non-Secure state +// ADC1_2_IRQn <0=> Secure state <1=> Non-Secure state +// CSI_IRQn <0=> Secure state <1=> Non-Secure state +// DCMIPP_IRQn <0=> Secure state <1=> Non-Secure state +// Reserved <0=> Secure state <1=> Non-Secure state +// Reserved <0=> Secure state <1=> Non-Secure state +// Reserved <0=> Secure state <1=> Non-Secure state +// PAHB_ERR_IRQn <0=> Secure state <1=> Non-Secure state +// NPU0_IRQn <0=> Secure state <1=> Non-Secure state +// NPU1_IRQn <0=> Secure state <1=> Non-Secure state +// NPU2_IRQn <0=> Secure state <1=> Non-Secure state +// NPU3_IRQn <0=> Secure state <1=> Non-Secure state +// CACHEAXI_IRQn <0=> Secure state <1=> Non-Secure state +// LTDC_LO_IRQn <0=> Secure state <1=> Non-Secure state +// LTDC_LO_ERR_IRQn <0=> Secure state <1=> Non-Secure state +// DMA2D_IRQn <0=> Secure state <1=> Non-Secure state +// JPEG_IRQn <0=> Secure state <1=> Non-Secure state +// VENC_IRQn <0=> Secure state <1=> Non-Secure state +// GFXMMU_IRQn <0=> Secure state <1=> Non-Secure state +*/ +#define NVIC_INIT_ITNS1_VAL 0x00000000 + +/* +// +*/ + +/* +// Initialize ITNS 2 (Interrupts 64..95) +*/ +#define NVIC_INIT_ITNS2 1 + +/* +// Interrupts 64..95 +// GFXTIM_IRQn <0=> Secure state <1=> Non-Secure state +// GPU2D_IRQn <0=> Secure state <1=> Non-Secure state +// GPU2D_ER_IRQn <0=> Secure state <1=> Non-Secure state +// ICACHE_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel0_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel1_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel2_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel3_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel4_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel5_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel6_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel7_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel8_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel9_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel10_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel11_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel12_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel13_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel14_IRQn <0=> Secure state <1=> Non-Secure state +// HPDMA1_Channel15_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel0_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel1_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel2_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel3_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel4_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel5_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel6_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel7_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel8_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel9_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel10_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel11_IRQn <0=> Secure state <1=> Non-Secure state +*/ +#define NVIC_INIT_ITNS2_VAL 0x00000000 + +/* +// +*/ + +/* +// Initialize ITNS 3 (Interrupts 96..127) +*/ +#define NVIC_INIT_ITNS3 1 + +/* +// Interrupts 96..127 +// GPDMA1_Channel12_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel13_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel14_IRQn <0=> Secure state <1=> Non-Secure state +// GPDMA1_Channel15_IRQn <0=> Secure state <1=> Non-Secure state +// I2C1_EV_IRQn <0=> Secure state <1=> Non-Secure state +// I2C1_ER_IRQn <0=> Secure state <1=> Non-Secure state +// I2C2_EV_IRQn <0=> Secure state <1=> Non-Secure state +// I2C2_ER_IRQn <0=> Secure state <1=> Non-Secure state +// I2C3_EV_IRQn <0=> Secure state <1=> Non-Secure state +// I2C3_ER_IRQn <0=> Secure state <1=> Non-Secure state +// I2C4_EV_IRQn <0=> Secure state <1=> Non-Secure state +// I2C4_ER_IRQn <0=> Secure state <1=> Non-Secure state +// I3C1_EV_IRQn <0=> Secure state <1=> Non-Secure state +// I3C1_ER_IRQn <0=> Secure state <1=> Non-Secure state +// I3C2_EV_IRQn <0=> Secure state <1=> Non-Secure state +// I3C2_ER_IRQn <0=> Secure state <1=> Non-Secure state +// TIM1_BRK_IRQn <0=> Secure state <1=> Non-Secure state +// TIM1_UP_IRQn <0=> Secure state <1=> Non-Secure state +// TIM1_TRG_COM_IRQn <0=> Secure state <1=> Non-Secure state +// TIM1_CC_IRQn <0=> Secure state <1=> Non-Secure state +// TIM2_IRQn <0=> Secure state <1=> Non-Secure state +// TIM3_IRQn <0=> Secure state <1=> Non-Secure state +// TIM4_IRQn <0=> Secure state <1=> Non-Secure state +// TIM5_IRQn <0=> Secure state <1=> Non-Secure state +// TIM6_IRQn <0=> Secure state <1=> Non-Secure state +// TIM7_IRQn <0=> Secure state <1=> Non-Secure state +// TIM8_BRK_IRQn <0=> Secure state <1=> Non-Secure state +// TIM8_UP_IRQn <0=> Secure state <1=> Non-Secure state +// TIM8_TRG_COM_IRQn <0=> Secure state <1=> Non-Secure state +// TIM8_CC_IRQn <0=> Secure state <1=> Non-Secure state +// TIM9_IRQn <0=> Secure state <1=> Non-Secure state +// TIM10_IRQn <0=> Secure state <1=> Non-Secure state + +*/ +#define NVIC_INIT_ITNS3_VAL 0x00000000 + +/* +// +*/ + +/* +// Initialize ITNS 4 (Interrupts 128..159) +*/ +#define NVIC_INIT_ITNS4 1 + +/* +// Interrupts 128..159 +// TIM11_IRQn <0=> Secure state <1=> Non-Secure state +// TIM12_IRQn <0=> Secure state <1=> Non-Secure state +// TIM13_IRQn <0=> Secure state <1=> Non-Secure state +// TIM14_IRQn <0=> Secure state <1=> Non-Secure state +// TIM15_IRQn <0=> Secure state <1=> Non-Secure state +// TIM16_IRQn <0=> Secure state <1=> Non-Secure state +// TIM17_IRQn <0=> Secure state <1=> Non-Secure state +// TIM18_IRQn <0=> Secure state <1=> Non-Secure state +// LPTIM1_IRQn <0=> Secure state <1=> Non-Secure state +// LPTIM2_IRQn <0=> Secure state <1=> Non-Secure state +// LPTIM3_IRQn <0=> Secure state <1=> Non-Secure state +// LPTIM4_IRQn <0=> Secure state <1=> Non-Secure state +// LPTIM5_IRQn <0=> Secure state <1=> Non-Secure state +// ADF1_FLT0_IRQn <0=> Secure state <1=> Non-Secure state +// MDF1_FLT0_IRQn <0=> Secure state <1=> Non-Secure state +// MDF1_FLT1_IRQn <0=> Secure state <1=> Non-Secure state +// MDF1_FLT2_IRQn <0=> Secure state <1=> Non-Secure state +// MDF1_FLT3_IRQn <0=> Secure state <1=> Non-Secure state +// MDF1_FLT4_IRQn <0=> Secure state <1=> Non-Secure state +// MDF1_FLT5_IRQn <0=> Secure state <1=> Non-Secure state +// SAI1_A_IRQn <0=> Secure state <1=> Non-Secure state +// SAI1_B_IRQn <0=> Secure state <1=> Non-Secure state +// SAI2_A_IRQn <0=> Secure state <1=> Non-Secure state +// SAI2_B_IRQn <0=> Secure state <1=> Non-Secure state +// SPDIFRX1_IRQn <0=> Secure state <1=> Non-Secure state +// SPI1_IRQn <0=> Secure state <1=> Non-Secure state +// SPI2_IRQn <0=> Secure state <1=> Non-Secure state +// SPI3_IRQn <0=> Secure state <1=> Non-Secure state +// SPI4_IRQn <0=> Secure state <1=> Non-Secure state +// SPI5_IRQn <0=> Secure state <1=> Non-Secure state +// SPI6_IRQn <0=> Secure state <1=> Non-Secure state +// USART1_IRQn <0=> Secure state <1=> Non-Secure state + +*/ +#define NVIC_INIT_ITNS4_VAL 0x00000000 + +/* +// +*/ + +/* +// Initialize ITNS 5 (Interrupts 160..191) +*/ +#define NVIC_INIT_ITNS5 1 + +/* +// Interrupts 160..191 +// USART2_IRQn <0=> Secure state <1=> Non-Secure state +// USART3_IRQn <0=> Secure state <1=> Non-Secure state +// UART4_IRQn <0=> Secure state <1=> Non-Secure state +// UART5_IRQn <0=> Secure state <1=> Non-Secure state +// USART6_IRQn <0=> Secure state <1=> Non-Secure state +// UART7_IRQn <0=> Secure state <1=> Non-Secure state +// UART8_IRQn <0=> Secure state <1=> Non-Secure state +// UART9_IRQn <0=> Secure state <1=> Non-Secure state +// USART10_IRQn <0=> Secure state <1=> Non-Secure state +// LPUART1_IRQn <0=> Secure state <1=> Non-Secure state +// XSPI1_IRQn <0=> Secure state <1=> Non-Secure state +// XSPI2_IRQn <0=> Secure state <1=> Non-Secure state +// XSPI3_IRQn <0=> Secure state <1=> Non-Secure state +// FMC_IRQn <0=> Secure state <1=> Non-Secure state +// SDMMC1_IRQn <0=> Secure state <1=> Non-Secure state +// SDMMC2_IRQn <0=> Secure state <1=> Non-Secure state +// UCPD1_IRQn <0=> Secure state <1=> Non-Secure state +// USB1_OTG_HS_IRQn <0=> Secure state <1=> Non-Secure state +// USB2_OTG_HS_IRQn <0=> Secure state <1=> Non-Secure state +// ETH1_IRQn <0=> Secure state <1=> Non-Secure state +// FDCAN1_IT0_IRQn <0=> Secure state <1=> Non-Secure state +// FDCAN1_IT1_IRQn <0=> Secure state <1=> Non-Secure state +// FDCAN2_IT0_IRQn <0=> Secure state <1=> Non-Secure state +// FDCAN2_IT1_IRQn <0=> Secure state <1=> Non-Secure state +// FDCAN3_IT0_IRQn <0=> Secure state <1=> Non-Secure state +// FDCAN3_IT1_IRQn <0=> Secure state <1=> Non-Secure state +// FDCAN_CU_IRQn <0=> Secure state <1=> Non-Secure state +// MDIOS_IRQn <0=> Secure state <1=> Non-Secure state +// DCMI_PSSI_IRQn <0=> Secure state <1=> Non-Secure state +// WAKEUP_PIN_IRQn <0=> Secure state <1=> Non-Secure state +// CTI_INT0_IRQn <0=> Secure state <1=> Non-Secure state +// CTI_INT1_IRQn <0=> Secure state <1=> Non-Secure state + +*/ +#define NVIC_INIT_ITNS5_VAL 0x00000000 + +/* +// +*/ + +/* +// Initialize ITNS 6 (Interrupts 192..223) +*/ +#define NVIC_INIT_ITNS6 1 + +/* +// Interrupts 192..223 +// Reserved <0=> Secure state <1=> Non-Secure state +// LTDC_UP_IRQn <0=> Secure state <1=> Non-Secure state +// LTDC_UP_ERR_IRQn <0=> Secure state <1=> Non-Secure state + +*/ +#define NVIC_INIT_ITNS6_VAL 0x00000000 + +/* +// +*/ + +/* +// +*/ + + + +/* + max 8 SAU regions. + SAU regions are defined in partition.h + */ + +#define SAU_INIT_REGION(n) \ + SAU->RNR = (n & SAU_RNR_REGION_Msk); \ + SAU->RBAR = (SAU_INIT_START##n & SAU_RBAR_BADDR_Msk); \ + SAU->RLAR = (SAU_INIT_END##n & SAU_RLAR_LADDR_Msk) | \ + ((SAU_INIT_NSC##n << SAU_RLAR_NSC_Pos) & SAU_RLAR_NSC_Msk) | 1U + +/** + \brief Setup a SAU Region + \details Writes the region information contained in SAU_Region to the + registers SAU_RNR, SAU_RBAR, and SAU_RLAR + */ +__STATIC_INLINE void TZ_SAU_Setup (void) +{ + +#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) + + #if defined (SAU_INIT_REGION0) && (SAU_INIT_REGION0 == 1U) + SAU_INIT_REGION(0); + #endif + + #if defined (SAU_INIT_REGION1) && (SAU_INIT_REGION1 == 1U) + SAU_INIT_REGION(1); + #endif + + #if defined (SAU_INIT_REGION2) && (SAU_INIT_REGION2 == 1U) + SAU_INIT_REGION(2); + #endif + + #if defined (SAU_INIT_REGION3) && (SAU_INIT_REGION3 == 1U) + SAU_INIT_REGION(3); + #endif + + #if defined (SAU_INIT_REGION4) && (SAU_INIT_REGION4 == 1U) + SAU_INIT_REGION(4); + #endif + + #if defined (SAU_INIT_REGION5) && (SAU_INIT_REGION5 == 1U) + SAU_INIT_REGION(5); + #endif + + #if defined (SAU_INIT_REGION6) && (SAU_INIT_REGION6 == 1U) + SAU_INIT_REGION(6); + #endif + + #if defined (SAU_INIT_REGION7) && (SAU_INIT_REGION7 == 1U) + SAU_INIT_REGION(7); + #endif + + /* repeat this for all possible SAU regions */ + +#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */ + + + #if defined (SAU_INIT_CTRL) && (SAU_INIT_CTRL == 1U) + SAU->CTRL = ((SAU_INIT_CTRL_ENABLE << SAU_CTRL_ENABLE_Pos) & SAU_CTRL_ENABLE_Msk) | + ((SAU_INIT_CTRL_ALLNS << SAU_CTRL_ALLNS_Pos) & SAU_CTRL_ALLNS_Msk) ; + #endif + + #if defined (SCB_CSR_AIRCR_INIT) && (SCB_CSR_AIRCR_INIT == 1U) + SCB->SCR = (SCB->SCR & ~(SCB_SCR_SLEEPDEEPS_Msk )) | + ((SCB_CSR_DEEPSLEEPS_VAL << SCB_SCR_SLEEPDEEPS_Pos) & SCB_SCR_SLEEPDEEPS_Msk); + + SCB->AIRCR = (SCB->AIRCR & ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_SYSRESETREQS_Msk | + SCB_AIRCR_BFHFNMINS_Msk | SCB_AIRCR_PRIS_Msk) ) | + ((0x05FAU << SCB_AIRCR_VECTKEY_Pos) & SCB_AIRCR_VECTKEY_Msk) | + ((SCB_AIRCR_SYSRESETREQS_VAL << SCB_AIRCR_SYSRESETREQS_Pos) & SCB_AIRCR_SYSRESETREQS_Msk) | + ((SCB_AIRCR_PRIS_VAL << SCB_AIRCR_PRIS_Pos) & SCB_AIRCR_PRIS_Msk) | + ((SCB_AIRCR_BFHFNMINS_VAL << SCB_AIRCR_BFHFNMINS_Pos) & SCB_AIRCR_BFHFNMINS_Msk); + #endif /* defined (SCB_CSR_AIRCR_INIT) && (SCB_CSR_AIRCR_INIT == 1U) */ + + #if defined (__FPU_USED) && (__FPU_USED == 1U) && \ + defined (TZ_FPU_NS_USAGE) && (TZ_FPU_NS_USAGE == 1U) + + SCB->NSACR = (SCB->NSACR & ~(SCB_NSACR_CP10_Msk | SCB_NSACR_CP11_Msk)) | + ((SCB_NSACR_CP10_11_VAL << SCB_NSACR_CP10_Pos) & (SCB_NSACR_CP10_Msk | SCB_NSACR_CP11_Msk)); + + FPU->FPCCR = (FPU->FPCCR & ~(FPU_FPCCR_TS_Msk | FPU_FPCCR_CLRONRETS_Msk | FPU_FPCCR_CLRONRET_Msk)) | + ((FPU_FPCCR_TS_VAL << FPU_FPCCR_TS_Pos ) & FPU_FPCCR_TS_Msk ) | + ((FPU_FPCCR_CLRONRETS_VAL << FPU_FPCCR_CLRONRETS_Pos) & FPU_FPCCR_CLRONRETS_Msk) | + ((FPU_FPCCR_CLRONRET_VAL << FPU_FPCCR_CLRONRET_Pos ) & FPU_FPCCR_CLRONRET_Msk ); + #endif + + #if defined (NVIC_INIT_ITNS0) && (NVIC_INIT_ITNS0 == 1U) + NVIC->ITNS[0] = NVIC_INIT_ITNS0_VAL; + #endif + + #if defined (NVIC_INIT_ITNS1) && (NVIC_INIT_ITNS1 == 1U) + NVIC->ITNS[1] = NVIC_INIT_ITNS1_VAL; + #endif + + #if defined (NVIC_INIT_ITNS2) && (NVIC_INIT_ITNS2 == 1U) + NVIC->ITNS[2] = NVIC_INIT_ITNS2_VAL; + #endif + + #if defined (NVIC_INIT_ITNS3) && (NVIC_INIT_ITNS3 == 1U) + NVIC->ITNS[3] = NVIC_INIT_ITNS3_VAL; + #endif + + #if defined (NVIC_INIT_ITNS4) && (NVIC_INIT_ITNS4 == 1U) + NVIC->ITNS[4] = NVIC_INIT_ITNS4_VAL; + #endif + + #if defined (NVIC_INIT_ITNS5) && (NVIC_INIT_ITNS5 == 1U) + NVIC->ITNS[5] = NVIC_INIT_ITNS5_VAL; + #endif + + #if defined (NVIC_INIT_ITNS6) && (NVIC_INIT_ITNS6 == 1U) + NVIC->ITNS[6] = NVIC_INIT_ITNS6_VAL; + #endif + +} + +#endif /* PARTITION_STM32N657XX_H */ diff --git a/hw/bsp/stm32n6/stm32n6xx_hal_conf.h b/hw/bsp/stm32n6/stm32n6xx_hal_conf.h new file mode 100644 index 000000000..d98d365a3 --- /dev/null +++ b/hw/bsp/stm32n6/stm32n6xx_hal_conf.h @@ -0,0 +1,504 @@ +/** + ****************************************************************************** + * @file stm32n6xx_hal_conf_template.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32n6xx_hal_conf.h. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32N6xx_HAL_CONF_H +#define STM32N6xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +/*#define HAL_ADC_MODULE_ENABLED */ +/*#define HAL_BSEC_MODULE_ENABLED */ +/*#define HAL_CRC_MODULE_ENABLED */ +/*#define HAL_CRYP_MODULE_ENABLED */ +/*#define HAL_DCMI_MODULE_ENABLED */ +/*#define HAL_DCMIPP_MODULE_ENABLED */ +/*#define HAL_DMA2D_MODULE_ENABLED */ +/*#define HAL_DTS_MODULE_ENABLED */ +/*#define HAL_ETH_MODULE_ENABLED */ +/*#define HAL_EXTI_MODULE_ENABLED */ +/*#define HAL_FDCAN_MODULE_ENABLED */ +/*#define HAL_GFXMMU_MODULE_ENABLED */ +/*#define HAL_GFXTIM_MODULE_ENABLED */ +/*#define HAL_HASH_MODULE_ENABLED */ +#define HAL_HCD_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +/*#define HAL_I2S_MODULE_ENABLED */ +/*#define HAL_I3C_MODULE_ENABLED */ +/*#define HAL_ICACHE_MODULE_ENABLED */ +/*#define HAL_IRDA_MODULE_ENABLED */ +/*#define HAL_IWDG_MODULE_ENABLED */ +/*#define HAL_JPEG_MODULE_ENABLED */ +/*#define HAL_LPTIM_MODULE_ENABLED */ +/*#define HAL_LTDC_MODULE_ENABLED */ +/*#define HAL_MCE_MODULE_ENABLED */ +/*#define HAL_MDF_MODULE_ENABLED */ +/*#define HAL_MMC_MODULE_ENABLED */ +/*#define HAL_NAND_MODULE_ENABLED */ +/*#define HAL_NOR_MODULE_ENABLED */ +#define HAL_PCD_MODULE_ENABLED +/*#define HAL_PKA_MODULE_ENABLED */ +/*#define HAL_PSSI_MODULE_ENABLED */ +/*#define HAL_RAMCFG_MODULE_ENABLED */ +#define HAL_RIF_MODULE_ENABLED +/*#define HAL_RNG_MODULE_ENABLED */ +/*#define HAL_RTC_MODULE_ENABLED */ +/*#define HAL_SAI_MODULE_ENABLED */ +/*#define HAL_SD_MODULE_ENABLED */ +/*#define HAL_SDIO_MODULE_ENABLED */ +/*#define HAL_SDRAM_MODULE_ENABLED */ +/*#define HAL_SMARTCARD_MODULE_ENABLED*/ +/*#define HAL_SMBUS_MODULE_ENABLED */ +/*#define HAL_SPDIFRX_MODULE_ENABLED */ +/*#define HAL_SPI_MODULE_ENABLED */ +/*#define HAL_SRAM_MODULE_ENABLED */ +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +/*#define HAL_WWDG_MODULE_ENABLED */ +/*#define HAL_XSPI_MODULE_ENABLED */ +/*#define HAL_CACHEAXI_MODULE_ENABLED */ +/*#define HAL_MDIOS_MODULE_ENABLED */ +/*#define HAL_GPU2D_MODULE_ENABLED */ +/*#define HAL_CACHEAXI_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) +#define HSE_VALUE 48000000UL /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT 100UL /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) +#define LSE_VALUE 32768UL /*!< Value of the External oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT 5000UL /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal Multiple Speed oscillator (MSI) default value. + * This value is the default MSI range value after Reset. + */ +#if !defined (MSI_VALUE) +#define MSI_VALUE 4000000UL /*!< Value of the Internal oscillator in Hz */ +#endif /* MSI_VALUE */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) +#define HSI_VALUE 64000000UL /*!< Value of the Internal oscillator in Hz */ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) +#define LSI_VALUE 32000UL /*!< LSI Typical Value in Hz */ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz */ +/* The real value may vary depending on the variations in voltage and temperature.*/ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300UL /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY 15U /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Register callback feature configuration ############### */ +/** + * @brief Set below the peripheral configuration to "1U" to add the support + * of HAL callback registration/unregistration feature for the HAL + * driver(s). This allows user application to provide specific callback + * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting + * the default weak callback functions (see each stm32n6xx_hal_ppp.h file + * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef + * for each PPP peripheral). + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CACHEAXI_REGISTER_CALLBACKS 0U /* CACHEAXI register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DCMIPP_REGISTER_CALLBACKS 0U /* DCMIPP register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DTS_REGISTER_CALLBACKS 0U /* DTS register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_GFXMMU_REGISTER_CALLBACKS 0U /* GFXMMU register callback disabled */ +#define USE_HAL_GFXTIM_REGISTER_CALLBACKS 0U /* GFXTIM register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_I3C_REGISTER_CALLBACKS 0U /* I3C register callback disabled */ +#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U /* IWDG register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MCE_REGISTER_CALLBACKS 0U /* MCE register callback disabled */ +#define USE_HAL_MDF_REGISTER_CALLBACKS 0U /* MDF register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_PKA_REGISTER_CALLBACKS 0U /* PKA register callback disabled */ +#define USE_HAL_PSSI_REGISTER_CALLBACKS 0U /* PSSI register callback disabled */ +#define USE_HAL_RAMCFG_REGISTER_CALLBACKS 0U /* RAMCFG register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SDIO_REGISTER_CALLBACKS 0U /* SDIO register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ +#define USE_HAL_XSPI_REGISTER_CALLBACKS 0U /* XSPI register callback disabled */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ +#define USE_SPI_CRC 0U + +/* ################## SDMMC peripheral configuration ######################### */ + +#define USE_SD_TRANSCEIVER 0U + +/* ################## SDIO peripheral configuration ########################## */ +#define USE_SDIO_TRANSCEIVER 1U +#define SDIO_MAX_IO_NUMBER 7U /*!< SDIO device support maximum IO number */ + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32n6xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32n6xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_RIF_MODULE_ENABLED +#include "stm32n6xx_hal_rif.h" +#endif /* HAL_RIF_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32n6xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CACHEAXI_MODULE_ENABLED +#include "stm32n6xx_hal_cacheaxi.h" +#endif /* HAL_CACHEAXI_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32n6xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32n6xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_BSEC_MODULE_ENABLED +#include "stm32n6xx_hal_bsec.h" +#endif /* HAL_BSEC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32n6xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32n6xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED +#include "stm32n6xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_DCMIPP_MODULE_ENABLED +#include "stm32n6xx_hal_dcmipp.h" +#endif /* HAL_DCMIPP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED +#include "stm32n6xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DTS_MODULE_ENABLED +#include "stm32n6xx_hal_dts.h" +#endif /* HAL_DTS_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED +#include "stm32n6xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32n6xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_FDCAN_MODULE_ENABLED +#include "stm32n6xx_hal_fdcan.h" +#endif /* HAL_FDCAN_MODULE_ENABLED */ + +#ifdef HAL_GFXMMU_MODULE_ENABLED +#include "stm32n6xx_hal_gfxmmu.h" +#endif /* HAL_GFXMMU_MODULE_ENABLED */ + +#ifdef HAL_GFXTIM_MODULE_ENABLED +#include "stm32n6xx_hal_gfxtim.h" +#endif /* HAL_GFXTIM_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32n6xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_GPU2D_MODULE_ENABLED +#include "stm32n6xx_hal_gpu2d.h" +#endif /* HAL_GPU2D_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED +#include "stm32n6xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED +#include "stm32n6xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32n6xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32n6xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_I3C_MODULE_ENABLED +#include "stm32n6xx_hal_i3c.h" +#endif /* HAL_I3C_MODULE_ENABLED */ + +#ifdef HAL_ICACHE_MODULE_ENABLED +#include "stm32n6xx_hal_icache.h" +#endif /* HAL_ICACHE_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32n6xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32n6xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_JPEG_MODULE_ENABLED +#include "stm32n6xx_hal_jpeg.h" +#endif /* HAL_JPEG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32n6xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED +#include "stm32n6xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_MCE_MODULE_ENABLED +#include "stm32n6xx_hal_mce.h" +#endif /* HAL_MCE_MODULE_ENABLED */ + +#ifdef HAL_MDF_MODULE_ENABLED +#include "stm32n6xx_hal_mdf.h" +#endif /* HAL_MDF_MODULE_ENABLED */ + +#ifdef HAL_MDIOS_MODULE_ENABLED +#include "stm32n6xx_hal_mdios.h" +#endif /* HAL_MDIOS_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED +#include "stm32n6xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32n6xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED +#include "stm32n6xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED +#include "stm32n6xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32n6xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_PKA_MODULE_ENABLED +#include "stm32n6xx_hal_pka.h" +#endif /* HAL_PKA_MODULE_ENABLED */ + +#ifdef HAL_PSSI_MODULE_ENABLED +#include "stm32n6xx_hal_pssi.h" +#endif /* HAL_PSSI_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32n6xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RAMCFG_MODULE_ENABLED +#include "stm32n6xx_hal_ramcfg.h" +#endif /* HAL_RAMCFG_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32n6xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32n6xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED +#include "stm32n6xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED +#include "stm32n6xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SDIO_MODULE_ENABLED +#include "stm32n6xx_hal_sdio.h" +#endif /* HAL_SDIO_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED +#include "stm32n6xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32n6xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED +#include "stm32n6xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED +#include "stm32n6xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32n6xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED +#include "stm32n6xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32n6xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32n6xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32n6xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32n6xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_XSPI_MODULE_ENABLED +#include "stm32n6xx_hal_xspi.h" +#endif /* HAL_XSPI_MODULE_ENABLED */ + +/* Exported macros -----------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ +void assert_failed(uint8_t *file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32N6xx_HAL_CONF_H */ diff --git a/hw/bsp/zephyr_board_aliases.cmake b/hw/bsp/zephyr_board_aliases.cmake index 91ffc3a39..b85ecec81 100644 --- a/hw/bsp/zephyr_board_aliases.cmake +++ b/hw/bsp/zephyr_board_aliases.cmake @@ -1 +1,2 @@ set(pca10056_BOARD_ALIAS nrf52840dk/nrf52840) +set(stm32n657nucleo_BOARD_ALIAS nucleo_n657x0_q) \ No newline at end of file diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 6678265b5..027446a85 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -322,6 +322,15 @@ // MCU with on-chip HS Phy #define TUP_RHPORT_HIGHSPEED 1 +#elif TU_CHECK_MCU(OPT_MCU_STM32N6) + #define TUP_USBIP_DWC2 + #define TUP_USBIP_DWC2_STM32 + + #define TUP_DCD_ENDPOINT_MAX 9 + + // MCU with on-chip HS Phy + #define TUP_RHPORT_HIGHSPEED 2 + //--------------------------------------------------------------------+ // Sony //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 865c51894..5f86d6b76 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -425,6 +425,11 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Clear A override, force B Valid dwc2->gotgctl = (dwc2->gotgctl & ~GOTGCTL_AVALOEN) | GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL; +#if CFG_TUSB_MCU == OPT_MCU_STM32N6 + // No hardware detection of Vbus B-session is available on the STM32N6 + dwc2->stm32_gccfg |= STM32_GCCFG_VBVALOVAL; +#endif + // Enable required interrupts dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py index 25edcf22d..38aa5656a 100755 --- a/src/portable/synopsys/dwc2/dwc2_info.py +++ b/src/portable/synopsys/dwc2/dwc2_info.py @@ -22,6 +22,7 @@ dwc2_reg_value = { 'ST H743/H750': [0x2300, 0x4F54330A, 0, 0x229FE190, 0x03B8D2E8, 0xE3F00030], 'ST L476 FS': [0x2000, 0x4F54310A, 0, 0x229ED520, 0x0200D1E8, 0x17F08030], 'ST U5A5 HS': [0x5000, 0x4F54411A, 0, 0x228FE052, 0x03B882E8, 0xE2103E30], + 'ST N6xx HS': [0x5000, 0x4F54411A, 0, 0x228FE052, 0x03B882E8, 0xE2103E30], 'XMC4500': [0xAEC000, 0x4F54292A, 0, 0x228F5930, 0x027A01E5, 0xDBF08030], 'GD32VF103': [0x1000, 0, 0, 0, 0, 0], } diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index c11c1eb05..0c1f835a9 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -77,6 +77,17 @@ extern "C" { #define EP_MAX_HS 9 #define EP_FIFO_SIZE_HS 4096 +#elif CFG_TUSB_MCU == OPT_MCU_STM32N6 + #include "stm32n6xx.h" + #define EP_MAX_FS 6 + #define EP_FIFO_SIZE_FS 1280 + + #define EP_MAX_HS 9 + #define EP_FIFO_SIZE_HS 4096 + + #define USB_OTG_HS_PERIPH_BASE USB1_OTG_HS_BASE + #define OTG_HS_IRQn USB1_OTG_HS_IRQn + #elif CFG_TUSB_MCU == OPT_MCU_STM32F7 #include "stm32f7xx.h" #define EP_MAX_FS 6 diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 2de15068a..257fa2833 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -381,6 +381,10 @@ bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // force host mode and wait for mode switch dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FDMOD) | GUSBCFG_FHMOD; +#if CFG_TUSB_MCU == OPT_MCU_STM32N6 + // No hardware detection of Vbus B-session is available on the STM32N6 + dwc2->stm32_gccfg &= ~STM32_GCCFG_VBVALOVAL; +#endif while ((dwc2->gintsts & GINTSTS_CMOD) != GINTSTS_CMODE_HOST) {} // configure fixed-allocated fifo scheme diff --git a/src/tusb_option.h b/src/tusb_option.h index 104f669c9..cca6096c6 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -94,6 +94,7 @@ #define OPT_MCU_STM32U0 316 ///< ST U0 #define OPT_MCU_STM32H7RS 317 ///< ST F7RS #define OPT_MCU_STM32C0 318 ///< ST C0 +#define OPT_MCU_STM32N6 319 ///< ST N6 // Sony #define OPT_MCU_CXD56 400 ///< SONY CXD56 diff --git a/tools/get_deps.py b/tools/get_deps.py index 1ce8be6c7..ab9d50585 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -118,6 +118,9 @@ deps_optional = { 'hw/mcu/st/cmsis_device_l5': ['https://github.com/STMicroelectronics/cmsis_device_l5.git', 'd922865fc0326a102c26211c44b8e42f52c1e53d', 'stm32l5'], + 'hw/mcu/st/cmsis_device_n6': ['https://github.com/STMicroelectronics/cmsis-device-n6.git', + 'f818b00f775444e8d19ef6cad822534c345e054f', + 'stm32n6'], 'hw/mcu/st/cmsis_device_u5': ['https://github.com/STMicroelectronics/cmsis_device_u5.git', '5ad9797c54ec3e55eff770fc9b3cd4a1aefc1309', 'stm32u5'], @@ -172,6 +175,9 @@ deps_optional = { 'hw/mcu/st/stm32l5xx_hal_driver': ['https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git', '675c32a75df37f39d50d61f51cb0dcf53f07e1cb', 'stm32l5'], + 'hw/mcu/st/stm32n6xx_hal_driver': ['https://github.com/STMicroelectronics/stm32n6xx-hal-driver.git', + '49f9989d10cf6817d4b07ac01848956b46bd0fd6', + 'stm32n6'], 'hw/mcu/st/stm32u5xx_hal_driver': ['https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git', '4d93097a67928e9377e655ddd14622adc31b9770', 'stm32u5'], @@ -198,7 +204,7 @@ deps_optional = { 'imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x ' 'lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 ' 'stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 ' - 'stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32u5 stm32wb ' + 'stm32h7 stm32l0 stm32l1 stm32l4 stm32l5 stm32n6 stm32u5 stm32wb ' 'sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg ' 'tm4c '], 'lib/CMSIS_6': ['https://github.com/ARM-software/CMSIS_6.git', From d62a521e7cbc4467895e03b9a4a1367b8bc2caf4 Mon Sep 17 00:00:00 2001 From: James Sandison Date: Wed, 4 Jun 2025 11:27:34 +1000 Subject: [PATCH 200/382] chore: add newline to EOF --- hw/bsp/zephyr_board_aliases.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/zephyr_board_aliases.cmake b/hw/bsp/zephyr_board_aliases.cmake index b85ecec81..b60e97ef4 100644 --- a/hw/bsp/zephyr_board_aliases.cmake +++ b/hw/bsp/zephyr_board_aliases.cmake @@ -1,2 +1,2 @@ set(pca10056_BOARD_ALIAS nrf52840dk/nrf52840) -set(stm32n657nucleo_BOARD_ALIAS nucleo_n657x0_q) \ No newline at end of file +set(stm32n657nucleo_BOARD_ALIAS nucleo_n657x0_q) From 001c7e3863e75a52f327799337d2c57dae024586 Mon Sep 17 00:00:00 2001 From: James Sandison Date: Wed, 4 Jun 2025 11:27:55 +1000 Subject: [PATCH 201/382] doc: remove reference to stm32n657_dk board --- docs/reference/boards.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 317a40c9c..251a6b7e9 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -269,7 +269,6 @@ stm32l412nucleo STM32 L412 Nucleo stm32l4 https://www.st stm32l476disco STM32 L476 Disco stm32l4 https://www.st.com/en/evaluation-tools/32l476gdiscovery.html stm32l4p5nucleo STM32 L4P5 Nucleo stm32l4 https://www.st.com/en/evaluation-tools/nucleo-l4p5zg.html stm32l4r5nucleo STM32 L4R5 Nucleo stm32l4 https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html -stm32n657_dk STM32 N657 Discovery Kit stm32n6 https://www.st.com/en/evaluation-tools/stm32n6570-dk.html stm32n657nucleo STM32 N657 Nucleo stm32n6 https://www.st.com/en/evaluation-tools/nucleo-n657x0-q.html b_u585i_iot2a STM32 B-U585i IOT2A Discovery kit stm32u5 https://www.st.com/en/evaluation-tools/b-u585i-iot02a.html stm32u545nucleo STM32 U545 Nucleo stm32u5 https://www.st.com/en/evaluation-tools/nucleo-u545re-q.html From 3cf7234d67f2cf3350cf0779a1ddd2e15e6a4b0e Mon Sep 17 00:00:00 2001 From: James Sandison Date: Wed, 4 Jun 2025 11:37:45 +1000 Subject: [PATCH 202/382] chore: whitespace fix --- hw/bsp/stm32n6/partition_stm32n657xx.h | 2 +- hw/mcu/st/cmsis_device_h7rs | 1 + hw/mcu/st/cmsis_device_n6 | 1 + hw/mcu/st/stm32h7rsxx_hal_driver | 1 + hw/mcu/st/stm32n6xx_hal_driver | 1 + lib/CMSIS_5 | 1 + lib/FreeRTOS-Kernel | 1 + lib/lwip | 1 + modules/crypto/mbedtls | 1 + modules/hal/cmsis | 1 + modules/hal/stm32 | 1 + tools/uf2 | 1 + zephyr | 1 + 13 files changed, 13 insertions(+), 1 deletion(-) create mode 160000 hw/mcu/st/cmsis_device_h7rs create mode 160000 hw/mcu/st/cmsis_device_n6 create mode 160000 hw/mcu/st/stm32h7rsxx_hal_driver create mode 160000 hw/mcu/st/stm32n6xx_hal_driver create mode 160000 lib/CMSIS_5 create mode 160000 lib/FreeRTOS-Kernel create mode 160000 lib/lwip create mode 160000 modules/crypto/mbedtls create mode 160000 modules/hal/cmsis create mode 160000 modules/hal/stm32 create mode 160000 tools/uf2 create mode 160000 zephyr diff --git a/hw/bsp/stm32n6/partition_stm32n657xx.h b/hw/bsp/stm32n6/partition_stm32n657xx.h index 713068609..4efdc5668 100644 --- a/hw/bsp/stm32n6/partition_stm32n657xx.h +++ b/hw/bsp/stm32n6/partition_stm32n657xx.h @@ -785,7 +785,7 @@ __STATIC_INLINE void TZ_SAU_Setup (void) #if defined (NVIC_INIT_ITNS6) && (NVIC_INIT_ITNS6 == 1U) NVIC->ITNS[6] = NVIC_INIT_ITNS6_VAL; - #endif + #endif } diff --git a/hw/mcu/st/cmsis_device_h7rs b/hw/mcu/st/cmsis_device_h7rs new file mode 160000 index 000000000..832649d1f --- /dev/null +++ b/hw/mcu/st/cmsis_device_h7rs @@ -0,0 +1 @@ +Subproject commit 832649d1fd09bd901e9f68e979522e5c209ebf20 diff --git a/hw/mcu/st/cmsis_device_n6 b/hw/mcu/st/cmsis_device_n6 new file mode 160000 index 000000000..f818b00f7 --- /dev/null +++ b/hw/mcu/st/cmsis_device_n6 @@ -0,0 +1 @@ +Subproject commit f818b00f775444e8d19ef6cad822534c345e054f diff --git a/hw/mcu/st/stm32h7rsxx_hal_driver b/hw/mcu/st/stm32h7rsxx_hal_driver new file mode 160000 index 000000000..7ca2e07ca --- /dev/null +++ b/hw/mcu/st/stm32h7rsxx_hal_driver @@ -0,0 +1 @@ +Subproject commit 7ca2e07ca21bc66b53654e845b4c85c884343b60 diff --git a/hw/mcu/st/stm32n6xx_hal_driver b/hw/mcu/st/stm32n6xx_hal_driver new file mode 160000 index 000000000..49f9989d1 --- /dev/null +++ b/hw/mcu/st/stm32n6xx_hal_driver @@ -0,0 +1 @@ +Subproject commit 49f9989d10cf6817d4b07ac01848956b46bd0fd6 diff --git a/lib/CMSIS_5 b/lib/CMSIS_5 new file mode 160000 index 000000000..2b7495b85 --- /dev/null +++ b/lib/CMSIS_5 @@ -0,0 +1 @@ +Subproject commit 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c diff --git a/lib/FreeRTOS-Kernel b/lib/FreeRTOS-Kernel new file mode 160000 index 000000000..cc0e0707c --- /dev/null +++ b/lib/FreeRTOS-Kernel @@ -0,0 +1 @@ +Subproject commit cc0e0707c0c748713485b870bb980852b210877f diff --git a/lib/lwip b/lib/lwip new file mode 160000 index 000000000..159e31b68 --- /dev/null +++ b/lib/lwip @@ -0,0 +1 @@ +Subproject commit 159e31b689577dbf69cf0683bbaffbd71fa5ee10 diff --git a/modules/crypto/mbedtls b/modules/crypto/mbedtls new file mode 160000 index 000000000..5f8899343 --- /dev/null +++ b/modules/crypto/mbedtls @@ -0,0 +1 @@ +Subproject commit 5f889934359deccf421554c7045a8381ef75298f diff --git a/modules/hal/cmsis b/modules/hal/cmsis new file mode 160000 index 000000000..d1b8b20b6 --- /dev/null +++ b/modules/hal/cmsis @@ -0,0 +1 @@ +Subproject commit d1b8b20b6278615b00e136374540eb1c00dcabe7 diff --git a/modules/hal/stm32 b/modules/hal/stm32 new file mode 160000 index 000000000..5cbc642b1 --- /dev/null +++ b/modules/hal/stm32 @@ -0,0 +1 @@ +Subproject commit 5cbc642b1a79d4f373b1587f8c3027f31bf0d30c diff --git a/tools/uf2 b/tools/uf2 new file mode 160000 index 000000000..c594542b2 --- /dev/null +++ b/tools/uf2 @@ -0,0 +1 @@ +Subproject commit c594542b2faa01cc33a2b97c9fbebc38549df80a diff --git a/zephyr b/zephyr new file mode 160000 index 000000000..c2c1495b4 --- /dev/null +++ b/zephyr @@ -0,0 +1 @@ +Subproject commit c2c1495b4c523a679a57e7b72891c02a34351f43 From efc8c08a66517054f38213be2e191ea60ac04333 Mon Sep 17 00:00:00 2001 From: James Sandison Date: Wed, 4 Jun 2025 11:42:21 +1000 Subject: [PATCH 203/382] chore: delete accidentally commited submodules --- hw/mcu/st/cmsis_device_h7rs | 1 - hw/mcu/st/cmsis_device_n6 | 1 - hw/mcu/st/stm32h7rsxx_hal_driver | 1 - hw/mcu/st/stm32n6xx_hal_driver | 1 - lib/CMSIS_5 | 1 - lib/FreeRTOS-Kernel | 1 - lib/lwip | 1 - modules/crypto/mbedtls | 1 - modules/hal/cmsis | 1 - modules/hal/stm32 | 1 - tools/uf2 | 1 - zephyr | 1 - 12 files changed, 12 deletions(-) delete mode 160000 hw/mcu/st/cmsis_device_h7rs delete mode 160000 hw/mcu/st/cmsis_device_n6 delete mode 160000 hw/mcu/st/stm32h7rsxx_hal_driver delete mode 160000 hw/mcu/st/stm32n6xx_hal_driver delete mode 160000 lib/CMSIS_5 delete mode 160000 lib/FreeRTOS-Kernel delete mode 160000 lib/lwip delete mode 160000 modules/crypto/mbedtls delete mode 160000 modules/hal/cmsis delete mode 160000 modules/hal/stm32 delete mode 160000 tools/uf2 delete mode 160000 zephyr diff --git a/hw/mcu/st/cmsis_device_h7rs b/hw/mcu/st/cmsis_device_h7rs deleted file mode 160000 index 832649d1f..000000000 --- a/hw/mcu/st/cmsis_device_h7rs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 832649d1fd09bd901e9f68e979522e5c209ebf20 diff --git a/hw/mcu/st/cmsis_device_n6 b/hw/mcu/st/cmsis_device_n6 deleted file mode 160000 index f818b00f7..000000000 --- a/hw/mcu/st/cmsis_device_n6 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f818b00f775444e8d19ef6cad822534c345e054f diff --git a/hw/mcu/st/stm32h7rsxx_hal_driver b/hw/mcu/st/stm32h7rsxx_hal_driver deleted file mode 160000 index 7ca2e07ca..000000000 --- a/hw/mcu/st/stm32h7rsxx_hal_driver +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7ca2e07ca21bc66b53654e845b4c85c884343b60 diff --git a/hw/mcu/st/stm32n6xx_hal_driver b/hw/mcu/st/stm32n6xx_hal_driver deleted file mode 160000 index 49f9989d1..000000000 --- a/hw/mcu/st/stm32n6xx_hal_driver +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 49f9989d10cf6817d4b07ac01848956b46bd0fd6 diff --git a/lib/CMSIS_5 b/lib/CMSIS_5 deleted file mode 160000 index 2b7495b85..000000000 --- a/lib/CMSIS_5 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c diff --git a/lib/FreeRTOS-Kernel b/lib/FreeRTOS-Kernel deleted file mode 160000 index cc0e0707c..000000000 --- a/lib/FreeRTOS-Kernel +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cc0e0707c0c748713485b870bb980852b210877f diff --git a/lib/lwip b/lib/lwip deleted file mode 160000 index 159e31b68..000000000 --- a/lib/lwip +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 159e31b689577dbf69cf0683bbaffbd71fa5ee10 diff --git a/modules/crypto/mbedtls b/modules/crypto/mbedtls deleted file mode 160000 index 5f8899343..000000000 --- a/modules/crypto/mbedtls +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5f889934359deccf421554c7045a8381ef75298f diff --git a/modules/hal/cmsis b/modules/hal/cmsis deleted file mode 160000 index d1b8b20b6..000000000 --- a/modules/hal/cmsis +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d1b8b20b6278615b00e136374540eb1c00dcabe7 diff --git a/modules/hal/stm32 b/modules/hal/stm32 deleted file mode 160000 index 5cbc642b1..000000000 --- a/modules/hal/stm32 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5cbc642b1a79d4f373b1587f8c3027f31bf0d30c diff --git a/tools/uf2 b/tools/uf2 deleted file mode 160000 index c594542b2..000000000 --- a/tools/uf2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c594542b2faa01cc33a2b97c9fbebc38549df80a diff --git a/zephyr b/zephyr deleted file mode 160000 index c2c1495b4..000000000 --- a/zephyr +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c2c1495b4c523a679a57e7b72891c02a34351f43 From 5c4b2c75d214fe9a7189dbcb91783d5b7841aa49 Mon Sep 17 00:00:00 2001 From: James Sandison Date: Wed, 4 Jun 2025 13:21:34 +1000 Subject: [PATCH 204/382] docs: update dwc2_info.md --- src/portable/synopsys/dwc2/dwc2_info.md | 116 ++++++++++++------------ 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/src/portable/synopsys/dwc2/dwc2_info.md b/src/portable/synopsys/dwc2/dwc2_info.md index dec021f59..230ab6b6f 100644 --- a/src/portable/synopsys/dwc2/dwc2_info.md +++ b/src/portable/synopsys/dwc2/dwc2_info.md @@ -1,58 +1,58 @@ -| | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5 HS | XMC4500 | GD32VF103 | -|:---------------------------|:----------------|:-------------|:--------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:-------------|:-------------|:------------| -| GUID | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00AEC000 | 0x00001000 | -| GSNPSID | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54292A | 0x00000000 | -| - specs version | 2.80a | 3.30a | 4.00a | 4.00a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 2.92a | 0.00W | -| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | -| GHWCFG2 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228F5930 | 0x00000000 | -| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | HNP SRP | HNP SRP | -| - arch | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | Slave only | -| - single_point | hub | hub | n/a | hub | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | n/a | hub | -| - hs_phy_type | UTMI+ | n/a | n/a | UTMI+/ULPI | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | n/a | n/a | -| - fs_phy_type | Dedicated | Dedicated | Dedicated | Shared ULPI | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | Dedicated | n/a | -| - num_dev_ep | 7 | 6 | 6 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | -| - num_host_ch | 7 | 13 | 7 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 13 | 0 | -| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - mul_proc_intrpt | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - nptx_q_depth | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - ptx_q_depth | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | -| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| GHWCFG3 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | -| - xfer_size_width | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | -| - packet_size_width | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | -| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - i2c_enable | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | -| - vendor_ctrl_itf | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | -| - optional_feature_removed | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - synch_reset | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - otg_adp_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - battery_charger_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | -| - dfifo_depth | 4080 | 498 | 200 | 896 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 634 | 0 | -| GHWCFG4 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | -| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - partial_powerdown | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - enhanced_lpm_support | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - phy_data_width | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8/16 bit | 8 bit | -| - ctrl_ep_num | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - iddg_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - vbus_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - a_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - b_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - session_end_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - num_dev_in_eps | 7 | 6 | 4 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | -| - dma_desc_enable | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | -| - dma_desc_dynamic | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | +| | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5 HS | ST N6xx HS | XMC4500 | GD32VF103 | +|:---------------------------|:----------------|:-------------|:--------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:-------------|:-------------|:-------------|:------------| +| GUID | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00005000 | 0x00AEC000 | 0x00001000 | +| GSNPSID | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54411A | 0x4F54292A | 0x00000000 | +| - specs version | 2.80a | 3.30a | 4.00a | 4.00a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 4.11a | 2.92a | 0.00W | +| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | +| GHWCFG2 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228FE052 | 0x228F5930 | 0x00000000 | +| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | noHNP noSRP | HNP SRP | HNP SRP | +| - arch | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | DMA internal | Slave only | +| - single_point | hub | hub | n/a | hub | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | hub | n/a | hub | +| - hs_phy_type | UTMI+ | n/a | n/a | UTMI+/ULPI | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | UTMI+ | n/a | n/a | +| - fs_phy_type | Dedicated | Dedicated | Dedicated | Shared ULPI | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | n/a | Dedicated | n/a | +| - num_dev_ep | 7 | 6 | 6 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 8 | 6 | 0 | +| - num_host_ch | 7 | 13 | 7 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 15 | 13 | 0 | +| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - mul_proc_intrpt | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | +| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - nptx_q_depth | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - ptx_q_depth | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | +| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| GHWCFG3 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | +| - xfer_size_width | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | +| - packet_size_width | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | +| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - i2c_enable | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | +| - vendor_ctrl_itf | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | +| - optional_feature_removed | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - synch_reset | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - otg_adp_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | +| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - battery_charger_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | +| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | +| - dfifo_depth | 4080 | 498 | 200 | 896 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 952 | 634 | 0 | +| GHWCFG4 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | +| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - partial_powerdown | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +| - enhanced_lpm_support | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | +| - phy_data_width | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | +| - ctrl_ep_num | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - iddg_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - vbus_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - a_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - b_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - session_end_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | +| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - num_dev_in_eps | 7 | 6 | 4 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 8 | 6 | 0 | +| - dma_desc_enable | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | +| - dma_desc_dynamic | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | From b956d10487e537dd1827a60c6786a490fd762dc4 Mon Sep 17 00:00:00 2001 From: James Sandison Date: Wed, 4 Jun 2025 13:52:35 +1000 Subject: [PATCH 205/382] fix: allow FreeRTOS examples to compile --- hw/bsp/stm32n6/FreeRTOSConfig/FreeRTOSConfig.h | 5 +++-- hw/bsp/stm32n6/family.c | 10 +++++++--- hw/bsp/stm32n6/stm32n6xx_hal_conf.h | 10 +++++----- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/hw/bsp/stm32n6/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32n6/FreeRTOSConfig/FreeRTOSConfig.h index 9fd3f6c50..a1b83c802 100644 --- a/hw/bsp/stm32n6/FreeRTOSConfig/FreeRTOSConfig.h +++ b/hw/bsp/stm32n6/FreeRTOSConfig/FreeRTOSConfig.h @@ -44,10 +44,11 @@ // skip if included from IAR assembler #ifndef __IASMARM__ - #include "stm32h7rsxx.h" + #include "stm32n6xx.h" #endif -/* Cortex M23/M33 port configuration. */ +/* Cortex M55 port configuration. */ +#define configENABLE_MVE 0 #define configENABLE_MPU 0 #define configENABLE_FPU 1 #define configENABLE_TRUSTZONE 0 diff --git a/hw/bsp/stm32n6/family.c b/hw/bsp/stm32n6/family.c index 0ec1875ac..1d0616d8e 100644 --- a/hw/bsp/stm32n6/family.c +++ b/hw/bsp/stm32n6/family.c @@ -145,7 +145,7 @@ void board_init(void) { // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); + NVIC_SetPriority(USB1_OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); #endif @@ -173,7 +173,9 @@ void board_init(void) { __HAL_RCC_USB1_OTG_HS_CLK_ENABLE(); /* Required few clock cycles before accessing USB PHY Controller Registers */ - HAL_Delay(1); + for (volatile uint32_t i = 0; i < 10; i++) { + __NOP(); // No Operation instruction to create a delay + } USB1_HS_PHYC->USBPHYC_CR &= ~(0x7 << 0x4); @@ -185,7 +187,9 @@ void board_init(void) { __HAL_RCC_USB1_OTG_HS_PHY_RELEASE_RESET(); /* Required few clock cycles before Releasing Reset */ - HAL_Delay(1); + for (volatile uint32_t i = 0; i < 10; i++) { + __NOP(); // No Operation instruction to create a delay + } __HAL_RCC_USB1_OTG_HS_RELEASE_RESET(); diff --git a/hw/bsp/stm32n6/stm32n6xx_hal_conf.h b/hw/bsp/stm32n6/stm32n6xx_hal_conf.h index d98d365a3..00cb31159 100644 --- a/hw/bsp/stm32n6/stm32n6xx_hal_conf.h +++ b/hw/bsp/stm32n6/stm32n6xx_hal_conf.h @@ -48,7 +48,7 @@ /*#define HAL_GFXMMU_MODULE_ENABLED */ /*#define HAL_GFXTIM_MODULE_ENABLED */ /*#define HAL_HASH_MODULE_ENABLED */ -#define HAL_HCD_MODULE_ENABLED +/*#define HAL_HCD_MODULE_ENABLED */ #define HAL_I2C_MODULE_ENABLED /*#define HAL_I2S_MODULE_ENABLED */ /*#define HAL_I3C_MODULE_ENABLED */ @@ -63,11 +63,11 @@ /*#define HAL_MMC_MODULE_ENABLED */ /*#define HAL_NAND_MODULE_ENABLED */ /*#define HAL_NOR_MODULE_ENABLED */ -#define HAL_PCD_MODULE_ENABLED +/*#define HAL_PCD_MODULE_ENABLED */ /*#define HAL_PKA_MODULE_ENABLED */ /*#define HAL_PSSI_MODULE_ENABLED */ /*#define HAL_RAMCFG_MODULE_ENABLED */ -#define HAL_RIF_MODULE_ENABLED +/*#define HAL_RIF_MODULE_ENABLED */ /*#define HAL_RNG_MODULE_ENABLED */ /*#define HAL_RTC_MODULE_ENABLED */ /*#define HAL_SAI_MODULE_ENABLED */ @@ -79,9 +79,9 @@ /*#define HAL_SPDIFRX_MODULE_ENABLED */ /*#define HAL_SPI_MODULE_ENABLED */ /*#define HAL_SRAM_MODULE_ENABLED */ -#define HAL_TIM_MODULE_ENABLED +/*#define HAL_TIM_MODULE_ENABLED */ #define HAL_UART_MODULE_ENABLED -#define HAL_USART_MODULE_ENABLED +/*#define HAL_USART_MODULE_ENABLED */ /*#define HAL_WWDG_MODULE_ENABLED */ /*#define HAL_XSPI_MODULE_ENABLED */ /*#define HAL_CACHEAXI_MODULE_ENABLED */ From 1ccb10e3f1418e51c03898f7ea2067208fd642b5 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 8 Jun 2025 13:53:23 +0200 Subject: [PATCH 206/382] Fix ECM compile Signed-off-by: HiFiPhile --- src/class/net/ecm_rndis_device.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/class/net/ecm_rndis_device.c b/src/class/net/ecm_rndis_device.c index f1a88b3c0..299eb97c8 100644 --- a/src/class/net/ecm_rndis_device.c +++ b/src/class/net/ecm_rndis_device.c @@ -186,8 +186,6 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1 // Open endpoint pair for RNDIS TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in), 0); - tud_network_init_cb(); - // we are ready to transmit a packet can_xmit = true; @@ -264,7 +262,6 @@ bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t // TODO should be merge with RNDIS's after endpoint opened // Also should have opposite callback for application to disable network !! - tud_network_init_cb(); can_xmit = true; // we are ready to transmit a packet tud_network_recv_renew(); // prepare for incoming packets } From 69f6b57772ad4f2923dcf48aabaaba044085c4b0 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 8 Jun 2025 14:27:57 +0200 Subject: [PATCH 207/382] Code reformat Signed-off-by: HiFiPhile --- src/class/usbtmc/usbtmc_device.c | 763 ++++++++++++++----------------- 1 file changed, 336 insertions(+), 427 deletions(-) diff --git a/src/class/usbtmc/usbtmc_device.c b/src/class/usbtmc/usbtmc_device.c index d47da101f..b79c3369c 100644 --- a/src/class/usbtmc/usbtmc_device.c +++ b/src/class/usbtmc/usbtmc_device.c @@ -76,11 +76,6 @@ #include "usbtmc_device.h" -#ifdef xDEBUG -#include "uart_util.h" -tu_static char logMsg[150]; -#endif - // Buffer size must be an exact multiple of the max packet size for both // bulk (up to 64 bytes for FS, 512 bytes for HS). In addation, this driver // imposes a minimum buffer size of 32 bytes. @@ -88,7 +83,7 @@ tu_static char logMsg[150]; // Interrupt endpoint buffer size, default to 2 bytes as USB488 specification. #ifndef CFG_TUD_USBTMC_INT_EP_SIZE -#define CFG_TUD_USBTMC_INT_EP_SIZE 2 + #define CFG_TUD_USBTMC_INT_EP_SIZE 2 #endif /* @@ -96,27 +91,26 @@ tu_static char logMsg[150]; * consistent with USBTMC. */ -typedef enum -{ - STATE_CLOSED, // Endpoints have not yet been opened since USB reset - STATE_NAK, // Bulk-out endpoint is in NAK state. - STATE_IDLE, // Bulk-out endpoint is waiting for CMD. - STATE_RCV, // Bulk-out is receiving DEV_DEP message +typedef enum { + STATE_CLOSED,// Endpoints have not yet been opened since USB reset + STATE_NAK, // Bulk-out endpoint is in NAK state. + STATE_IDLE, // Bulk-out endpoint is waiting for CMD. + STATE_RCV, // Bulk-out is receiving DEV_DEP message STATE_TX_REQUESTED, STATE_TX_INITIATED, STATE_TX_SHORTED, STATE_CLEARING, STATE_ABORTING_BULK_IN, - STATE_ABORTING_BULK_IN_SHORTED, // aborting, and short packet has been queued for transmission - STATE_ABORTING_BULK_IN_ABORTED, // aborting, and short packet has been transmitted + STATE_ABORTING_BULK_IN_SHORTED,// aborting, and short packet has been queued for transmission + STATE_ABORTING_BULK_IN_ABORTED,// aborting, and short packet has been transmitted STATE_ABORTING_BULK_OUT, STATE_NUM_STATES } usbtmcd_state_enum; #if (CFG_TUD_USBTMC_ENABLE_488) - typedef usbtmc_response_capabilities_488_t usbtmc_capabilities_specific_t; +typedef usbtmc_response_capabilities_488_t usbtmc_capabilities_specific_t; #else - typedef usbtmc_response_capabilities_t usbtmc_capabilities_specific_t; +typedef usbtmc_response_capabilities_t usbtmc_capabilities_specific_t; #endif @@ -131,15 +125,15 @@ typedef struct uint8_t ep_int_in; uint32_t ep_bulk_in_wMaxPacketSize; uint32_t ep_bulk_out_wMaxPacketSize; - uint32_t transfer_size_remaining; // also used for requested length for bulk IN. - uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes) + uint32_t transfer_size_remaining;// also used for requested length for bulk IN. + uint32_t transfer_size_sent; // To keep track of data bytes that have been queued in FIFO (not header bytes) - uint8_t lastBulkOutTag; // used for aborts (mostly) + uint8_t lastBulkOutTag;// used for aborts (mostly) uint8_t lastBulkInTag; // used for aborts (mostly) - uint8_t const * devInBuffer; // pointer to application-layer used for transmissions + uint8_t const *devInBuffer;// pointer to application-layer used for transmissions - usbtmc_capabilities_specific_t const * capabilities; + usbtmc_capabilities_specific_t const *capabilities; } usbtmc_interface_state_t; typedef struct { @@ -154,13 +148,13 @@ typedef struct { } usbtmc_epbuf_t; static usbtmc_interface_state_t usbtmc_state = { - .itf_id = 0xFF, + .itf_id = 0xFF, }; CFG_TUD_MEM_SECTION static usbtmc_epbuf_t usbtmc_epbuf; // We need all headers to fit in a single packet in this implementation, 32 bytes will fit all standard USBTMC headers -TU_VERIFY_STATIC(USBTMCD_BUFFER_SIZE >= 32u,"USBTMC dev buffer size too small"); +TU_VERIFY_STATIC(USBTMCD_BUFFER_SIZE >= 32u, "USBTMC dev buffer size too small"); static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len); static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen); @@ -179,20 +173,18 @@ static OSAL_MUTEX_DEF(usbtmcLockBuffer); osal_mutex_t usbtmcLock; // Our own private lock, mostly for the state variable. -#define criticalEnter() do { (void) osal_mutex_lock(usbtmcLock,OSAL_TIMEOUT_WAIT_FOREVER); } while (0) -#define criticalLeave() do { (void) osal_mutex_unlock(usbtmcLock); } while (0) +#define criticalEnter() \ + do { (void) osal_mutex_lock(usbtmcLock, OSAL_TIMEOUT_WAIT_FOREVER); } while (0) +#define criticalLeave() \ + do { (void) osal_mutex_unlock(usbtmcLock); } while (0) -static bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newState) -{ +static bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_enum newState) { bool ret = true; criticalEnter(); usbtmcd_state_enum oldState = usbtmc_state.state; - if (oldState == expectedState) - { + if (oldState == expectedState) { usbtmc_state.state = newState; - } - else - { + } else { ret = false; } criticalLeave(); @@ -207,61 +199,54 @@ static bool atomicChangeState(usbtmcd_state_enum expectedState, usbtmcd_state_en // We can't just send the whole thing at once because we need to concatanate the // header with the data. bool tud_usbtmc_transmit_dev_msg_data( - const void * data, size_t len, + const void *data, size_t len, bool endOfMessage, - bool usingTermChar) -{ + bool usingTermChar) { const unsigned int txBufLen = USBTMCD_BUFFER_SIZE; #ifndef NDEBUG TU_ASSERT(len > 0u); TU_ASSERT(len <= usbtmc_state.transfer_size_remaining); TU_ASSERT(usbtmc_state.transfer_size_sent == 0u); - if(usingTermChar) - { + if (usingTermChar) { TU_ASSERT(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); TU_ASSERT(termCharRequested); - TU_ASSERT(((uint8_t const*)data)[len-1u] == termChar); + TU_ASSERT(((uint8_t const *) data)[len - 1u] == termChar); } #endif TU_VERIFY(usbtmc_state.state == STATE_TX_REQUESTED); - usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t*)usbtmc_epbuf.epin; + usbtmc_msg_dev_dep_msg_in_header_t *hdr = (usbtmc_msg_dev_dep_msg_in_header_t *) usbtmc_epbuf.epin; tu_varclr(hdr); - if(usbtmcVendorSpecificRequested) - { + if (usbtmcVendorSpecificRequested) { hdr->header.MsgID = USBTMC_MSGID_VENDOR_SPECIFIC_IN; - } - else - { + } else { hdr->header.MsgID = USBTMC_MSGID_DEV_DEP_MSG_IN; } hdr->header.bTag = usbtmc_state.lastBulkInTag; - hdr->header.bTagInverse = (uint8_t)~(usbtmc_state.lastBulkInTag); + hdr->header.bTagInverse = (uint8_t) ~(usbtmc_state.lastBulkInTag); hdr->TransferSize = len; hdr->bmTransferAttributes.EOM = endOfMessage; hdr->bmTransferAttributes.UsingTermChar = usingTermChar; // Copy in the header const size_t headerLen = sizeof(*hdr); - const size_t dataLen = ((headerLen + hdr->TransferSize) <= txBufLen) ? - len : (txBufLen - headerLen); + const size_t dataLen = ((headerLen + hdr->TransferSize) <= txBufLen) ? len : (txBufLen - headerLen); const size_t packetLen = headerLen + dataLen; - memcpy((uint8_t*)(usbtmc_epbuf.epin) + headerLen, data, dataLen); + memcpy((uint8_t *) (usbtmc_epbuf.epin) + headerLen, data, dataLen); usbtmc_state.transfer_size_remaining = len - dataLen; usbtmc_state.transfer_size_sent = dataLen; - usbtmc_state.devInBuffer = (uint8_t const*) data + (dataLen); + usbtmc_state.devInBuffer = (uint8_t const *) data + (dataLen); bool stateChanged = atomicChangeState(STATE_TX_REQUESTED, (packetLen >= txBufLen) ? STATE_TX_INITIATED : STATE_TX_SHORTED); TU_VERIFY(stateChanged); - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t)packetLen)); + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) packetLen)); return true; } -bool tud_usbtmc_transmit_notification_data(const void * data, size_t len) -{ +bool tud_usbtmc_transmit_notification_data(const void *data, size_t len) { #ifndef NDEBUG TU_ASSERT(len > 0); TU_ASSERT(usbtmc_state.ep_int_in != 0); @@ -269,24 +254,23 @@ bool tud_usbtmc_transmit_notification_data(const void * data, size_t len) TU_VERIFY(usbd_edpt_busy(usbtmc_state.rhport, usbtmc_state.ep_int_in)); TU_VERIFY(tu_memcpy_s(usbtmc_epbuf.epnotif, CFG_TUD_USBTMC_INT_EP_SIZE, data, len) == 0); - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_int_in, usbtmc_epbuf.epnotif, (uint16_t)len)); + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_int_in, usbtmc_epbuf.epnotif, (uint16_t) len)); return true; } -void usbtmcd_init_cb(void) -{ +void usbtmcd_init_cb(void) { usbtmc_state.capabilities = tud_usbtmc_get_capabilities_cb(); #ifndef NDEBUG -# if CFG_TUD_USBTMC_ENABLE_488 + #if CFG_TUD_USBTMC_ENABLE_488 if (usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger) { - TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL,); + TU_ASSERT(&tud_usbtmc_msg_trigger_cb != NULL, ); } // Per USB488 spec: table 8 - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly,); - TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly,); -# endif + TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.listenOnly, ); + TU_ASSERT(!usbtmc_state.capabilities->bmIntfcCapabilities.talkOnly, ); + #endif if (usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse) { - TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL,); + TU_ASSERT(&tud_usbtmc_indicator_pulse_cb != NULL, ); } #endif @@ -294,26 +278,25 @@ void usbtmcd_init_cb(void) } bool usbtmcd_deinit(void) { - #if OSAL_MUTEX_REQUIRED +#if OSAL_MUTEX_REQUIRED osal_mutex_delete(usbtmcLock); - #endif +#endif return true; } -uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) -{ - (void)rhport; +uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { + (void) rhport; uint16_t drv_len; - uint8_t const * p_desc; + uint8_t const *p_desc; uint8_t found_endpoints = 0; - TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS , 0); + TU_VERIFY(itf_desc->bInterfaceClass == TUD_USBTMC_APP_CLASS, 0); TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_USBTMC_APP_SUBCLASS, 0); #ifndef NDEBUG // Only 2 or 3 endpoints are allowed for USBTMC. - TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints ==3), 0); + TU_ASSERT((itf_desc->bNumEndpoints == 2) || (itf_desc->bNumEndpoints == 3), 0); #endif TU_ASSERT(usbtmc_state.state == STATE_CLOSED, 0); @@ -325,17 +308,14 @@ uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, usbtmc_state.itf_id = itf_desc->bInterfaceNumber; usbtmc_state.rhport = rhport; - while (found_endpoints < itf_desc->bNumEndpoints && drv_len <= max_len) - { - if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) - { - tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc; - switch(ep_desc->bmAttributes.xfer) { + while (found_endpoints < itf_desc->bNumEndpoints && drv_len <= max_len) { + if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE]) { + tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *) p_desc; + switch (ep_desc->bmAttributes.xfer) { case TUSB_XFER_BULK: // Ensure buffer is an exact multiple of the maxPacketSize TU_ASSERT((USBTMCD_BUFFER_SIZE % tu_edpt_packet_size(ep_desc)) == 0, 0); - if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) - { + if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN) { usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress; usbtmc_state.ep_bulk_in_wMaxPacketSize = tu_edpt_packet_size(ep_desc); } else { @@ -354,33 +334,29 @@ uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, default: TU_ASSERT(false, 0); } - TU_ASSERT( usbd_edpt_open(rhport, ep_desc), 0); + TU_ASSERT(usbd_edpt_open(rhport, ep_desc), 0); found_endpoints++; } drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); } - // bulk endpoints are required, but interrupt IN is optional +// bulk endpoints are required, but interrupt IN is optional #ifndef NDEBUG - TU_ASSERT(usbtmc_state.ep_bulk_in != 0, 0); + TU_ASSERT(usbtmc_state.ep_bulk_in != 0, 0); TU_ASSERT(usbtmc_state.ep_bulk_out != 0, 0); - if (itf_desc->bNumEndpoints == 2) - { + if (itf_desc->bNumEndpoints == 2) { TU_ASSERT(usbtmc_state.ep_int_in == 0, 0); - } - else if (itf_desc->bNumEndpoints == 3) - { + } else if (itf_desc->bNumEndpoints == 3) { TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); } -#if (CFG_TUD_USBTMC_ENABLE_488) - if(usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 || - usbtmc_state.capabilities->bmDevCapabilities488.SR1) - { + #if (CFG_TUD_USBTMC_ENABLE_488) + if (usbtmc_state.capabilities->bmIntfcCapabilities488.is488_2 || + usbtmc_state.capabilities->bmDevCapabilities488.SR1) { TU_ASSERT(usbtmc_state.ep_int_in != 0, 0); } -#endif + #endif #endif atomicChangeState(STATE_CLOSED, STATE_NAK); tud_usbtmc_open_cb(itf_desc->iInterface); @@ -393,30 +369,27 @@ uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc, // processing a command (such as a clear). Returns true if it was // in the NAK state and successfully transitioned to the ACK wait // state. -bool tud_usbtmc_start_bus_read(void) -{ +bool tud_usbtmc_start_bus_read(void) { usbtmcd_state_enum oldState = usbtmc_state.state; - switch(oldState) - { - // These may transition to IDLE - case STATE_NAK: - case STATE_ABORTING_BULK_IN_ABORTED: - TU_VERIFY(atomicChangeState(oldState, STATE_IDLE)); - break; - // When receiving, let it remain receiving - case STATE_RCV: - break; - default: - return false; + switch (oldState) { + // These may transition to IDLE + case STATE_NAK: + case STATE_ABORTING_BULK_IN_ABORTED: + TU_VERIFY(atomicChangeState(oldState, STATE_IDLE)); + break; + // When receiving, let it remain receiving + case STATE_RCV: + break; + default: + return false; } - TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_epbuf.epout, (uint16_t)usbtmc_state.ep_bulk_out_wMaxPacketSize)); + TU_VERIFY(usbd_edpt_xfer(usbtmc_state.rhport, usbtmc_state.ep_bulk_out, usbtmc_epbuf.epout, (uint16_t) usbtmc_state.ep_bulk_out_wMaxPacketSize)); return true; } -void usbtmcd_reset_cb(uint8_t rhport) -{ - (void)rhport; - usbtmc_capabilities_specific_t const * capabilities = tud_usbtmc_get_capabilities_cb(); +void usbtmcd_reset_cb(uint8_t rhport) { + (void) rhport; + usbtmc_capabilities_specific_t const *capabilities = tud_usbtmc_get_capabilities_cb(); criticalEnter(); tu_varclr(&usbtmc_state); @@ -425,35 +398,32 @@ void usbtmcd_reset_cb(uint8_t rhport) criticalLeave(); } -static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) -{ - (void)rhport; +static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len) { + (void) rhport; // return true upon failure, as we can assume error is being handled elsewhere. TU_VERIFY(atomicChangeState(STATE_IDLE, STATE_RCV), true); usbtmc_state.transfer_size_sent = 0u; // must be a header, should have been confirmed before calling here. - usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out*)data; + usbtmc_msg_request_dev_dep_out *msg = (usbtmc_msg_request_dev_dep_out *) data; usbtmc_state.transfer_size_remaining = msg->TransferSize; TU_VERIFY(tud_usbtmc_msgBulkOut_start_cb(msg)); - TU_VERIFY(handle_devMsgOut(rhport, (uint8_t*)data + sizeof(*msg), len - sizeof(*msg), len)); + TU_VERIFY(handle_devMsgOut(rhport, (uint8_t *) data + sizeof(*msg), len - sizeof(*msg), len)); usbtmc_state.lastBulkOutTag = msg->header.bTag; return true; } -static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) -{ - (void)rhport; +static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen) { + (void) rhport; // return true upon failure, as we can assume error is being handled elsewhere. - TU_VERIFY(usbtmc_state.state == STATE_RCV,true); + TU_VERIFY(usbtmc_state.state == STATE_RCV, true); bool shortPacket = (packetLen < usbtmc_state.ep_bulk_out_wMaxPacketSize); // Packet is to be considered complete when we get enough data or at a short packet. bool atEnd = false; - if(len >= usbtmc_state.transfer_size_remaining || shortPacket) - { + if (len >= usbtmc_state.transfer_size_remaining || shortPacket) { atEnd = true; TU_VERIFY(atomicChangeState(STATE_RCV, STATE_NAK)); } @@ -464,8 +434,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack usbtmc_state.transfer_size_sent += len; // App may (should?) call the wait_for_bus() command at this point - if(!tud_usbtmc_msg_data_cb(data, len, atEnd)) - { + if (!tud_usbtmc_msg_data_cb(data, len, atEnd)) { // TODO: Go to an error state upon failure other than just stalling the EP? return false; } @@ -474,10 +443,9 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack return true; } -static bool handle_devMsgIn(void *data, size_t len) -{ +static bool handle_devMsgIn(void *data, size_t len) { TU_VERIFY(len == sizeof(usbtmc_msg_request_dev_dep_in)); - usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in*)data; + usbtmc_msg_request_dev_dep_in *msg = (usbtmc_msg_request_dev_dep_in *) data; bool stateChanged = atomicChangeState(STATE_IDLE, STATE_TX_REQUESTED); TU_VERIFY(stateChanged); usbtmc_state.lastBulkInTag = msg->header.bTag; @@ -490,148 +458,135 @@ static bool handle_devMsgIn(void *data, size_t len) termChar = msg->TermChar; #endif - if(termCharRequested) + if (termCharRequested) TU_VERIFY(usbtmc_state.capabilities->bmDevCapabilities.canEndBulkInOnTermChar); TU_VERIFY(tud_usbtmc_msgBulkIn_request_cb(msg)); return true; } -bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ +bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { TU_VERIFY(result == XFER_RESULT_SUCCESS); //uart_tx_str_sync("TMC XFER CB\r\n"); - if(usbtmc_state.state == STATE_CLEARING) { + if (usbtmc_state.state == STATE_CLEARING) { return true; /* I think we can ignore everything here */ } - if(ep_addr == usbtmc_state.ep_bulk_out) - { + if (ep_addr == usbtmc_state.ep_bulk_out) { usbtmc_msg_generic_t *msg = NULL; - switch(usbtmc_state.state) - { - case STATE_IDLE: - { + switch (usbtmc_state.state) { + case STATE_IDLE: { TU_VERIFY(xferred_bytes >= sizeof(usbtmc_msg_generic_t)); - msg = (usbtmc_msg_generic_t*)(usbtmc_epbuf.epout); - uint8_t invInvTag = (uint8_t)~(msg->header.bTagInverse); + msg = (usbtmc_msg_generic_t *) (usbtmc_epbuf.epout); + uint8_t invInvTag = (uint8_t) ~(msg->header.bTagInverse); TU_VERIFY(msg->header.bTag == invInvTag); TU_VERIFY(msg->header.bTag != 0x00); - switch(msg->header.MsgID) { - case USBTMC_MSGID_DEV_DEP_MSG_OUT: - usbtmcVendorSpecificRequested = false; - if(!handle_devMsgOutStart(rhport, msg, xferred_bytes)) - { - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - return false; - } - break; + switch (msg->header.MsgID) { + case USBTMC_MSGID_DEV_DEP_MSG_OUT: + usbtmcVendorSpecificRequested = false; + if (!handle_devMsgOutStart(rhport, msg, xferred_bytes)) { + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + return false; + } + break; - case USBTMC_MSGID_DEV_DEP_MSG_IN: - usbtmcVendorSpecificRequested = false; - TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); - break; + case USBTMC_MSGID_DEV_DEP_MSG_IN: + usbtmcVendorSpecificRequested = false; + TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); + break; #if (CFG_TUD_USBTMC_ENABLE_488) - case USBTMC_MSGID_USB488_TRIGGER: - // Spec says we halt the EP if we didn't declare we support it. - TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger); - TU_VERIFY(tud_usbtmc_msg_trigger_cb(msg)); + case USBTMC_MSGID_USB488_TRIGGER: + // Spec says we halt the EP if we didn't declare we support it. + TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities488.supportsTrigger); + TU_VERIFY(tud_usbtmc_msg_trigger_cb(msg)); - break; + break; #endif - case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: - usbtmcVendorSpecificRequested = true; - if(!handle_devMsgOutStart(rhport, msg, xferred_bytes)) - { + case USBTMC_MSGID_VENDOR_SPECIFIC_MSG_OUT: + usbtmcVendorSpecificRequested = true; + if (!handle_devMsgOutStart(rhport, msg, xferred_bytes)) { + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + return false; + } + break; + + case USBTMC_MSGID_VENDOR_SPECIFIC_IN: + usbtmcVendorSpecificRequested = true; + TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); + break; + + default: usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); return false; - } - break; - - case USBTMC_MSGID_VENDOR_SPECIFIC_IN: - usbtmcVendorSpecificRequested = true; - TU_VERIFY(handle_devMsgIn(msg, xferred_bytes)); - break; - - default: + } + return true; + } + case STATE_RCV: + if (!handle_devMsgOut(rhport, usbtmc_epbuf.epout, xferred_bytes, xferred_bytes)) { usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); return false; } return true; - } - case STATE_RCV: - if(!handle_devMsgOut(rhport, usbtmc_epbuf.epout, xferred_bytes, xferred_bytes)) - { - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); + + case STATE_ABORTING_BULK_OUT: + // Should be stalled by now, shouldn't have received a packet. return false; - } - return true; - case STATE_ABORTING_BULK_OUT: - // Should be stalled by now, shouldn't have received a packet. - return false; - - case STATE_TX_REQUESTED: - case STATE_TX_INITIATED: - case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_IN_SHORTED: - case STATE_ABORTING_BULK_IN_ABORTED: - default: - return false; + case STATE_TX_REQUESTED: + case STATE_TX_INITIATED: + case STATE_ABORTING_BULK_IN: + case STATE_ABORTING_BULK_IN_SHORTED: + case STATE_ABORTING_BULK_IN_ABORTED: + default: + return false; } - } - else if(ep_addr == usbtmc_state.ep_bulk_in) - { - switch(usbtmc_state.state) { - case STATE_TX_SHORTED: - TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); - TU_VERIFY(tud_usbtmc_msgBulkIn_complete_cb()); - break; + } else if (ep_addr == usbtmc_state.ep_bulk_in) { + switch (usbtmc_state.state) { + case STATE_TX_SHORTED: + TU_VERIFY(atomicChangeState(STATE_TX_SHORTED, STATE_NAK)); + TU_VERIFY(tud_usbtmc_msgBulkIn_complete_cb()); + break; - case STATE_TX_INITIATED: - if(usbtmc_state.transfer_size_remaining >= USBTMCD_BUFFER_SIZE) - { - // Copy buffer to ensure alignment correctness - memcpy(usbtmc_epbuf.epin, usbtmc_state.devInBuffer, USBTMCD_BUFFER_SIZE); - TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, USBTMCD_BUFFER_SIZE)); - usbtmc_state.devInBuffer += USBTMCD_BUFFER_SIZE; - usbtmc_state.transfer_size_remaining -= USBTMCD_BUFFER_SIZE; - usbtmc_state.transfer_size_sent += USBTMCD_BUFFER_SIZE; - } - else // last packet - { - size_t packetLen = usbtmc_state.transfer_size_remaining; - memcpy(usbtmc_epbuf.epin, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); - usbtmc_state.transfer_size_remaining = 0; - usbtmc_state.devInBuffer = NULL; - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t)packetLen) ); - if(((packetLen % usbtmc_state.ep_bulk_in_wMaxPacketSize) != 0) || (packetLen == 0 )) + case STATE_TX_INITIATED: + if (usbtmc_state.transfer_size_remaining >= USBTMCD_BUFFER_SIZE) { + // Copy buffer to ensure alignment correctness + memcpy(usbtmc_epbuf.epin, usbtmc_state.devInBuffer, USBTMCD_BUFFER_SIZE); + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, USBTMCD_BUFFER_SIZE)); + usbtmc_state.devInBuffer += USBTMCD_BUFFER_SIZE; + usbtmc_state.transfer_size_remaining -= USBTMCD_BUFFER_SIZE; + usbtmc_state.transfer_size_sent += USBTMCD_BUFFER_SIZE; + } else// last packet { - usbtmc_state.state = STATE_TX_SHORTED; + size_t packetLen = usbtmc_state.transfer_size_remaining; + memcpy(usbtmc_epbuf.epin, usbtmc_state.devInBuffer, usbtmc_state.transfer_size_remaining); + usbtmc_state.transfer_size_sent += sizeof(usbtmc_state.transfer_size_remaining); + usbtmc_state.transfer_size_remaining = 0; + usbtmc_state.devInBuffer = NULL; + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) packetLen)); + if (((packetLen % usbtmc_state.ep_bulk_in_wMaxPacketSize) != 0) || (packetLen == 0)) { + usbtmc_state.state = STATE_TX_SHORTED; + } } - } - return true; + return true; - case STATE_ABORTING_BULK_IN: - // need to send short packet (ZLP?) - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin,(uint16_t)0u)); - usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; - return true; + case STATE_ABORTING_BULK_IN: + // need to send short packet (ZLP?) + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) 0u)); + usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; + return true; - case STATE_ABORTING_BULK_IN_SHORTED: - /* Done. :)*/ - usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; - return true; + case STATE_ABORTING_BULK_IN_SHORTED: + /* Done. :)*/ + usbtmc_state.state = STATE_ABORTING_BULK_IN_ABORTED; + return true; - default: - TU_ASSERT(false); + default: + TU_ASSERT(false); } - } - else if (ep_addr == usbtmc_state.ep_int_in) { + } else if (ep_addr == usbtmc_state.ep_int_in) { if (tud_usbtmc_notification_complete_cb) { TU_VERIFY(tud_usbtmc_notification_complete_cb()); } @@ -643,188 +598,157 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint // Invoked when a control transfer occurred on an interface of this class // Driver response accordingly to the request and the transfer stage (setup/data/ack) // return false to stall control endpoint (e.g unsupported request) -bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request) -{ +bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) { // nothing to do with DATA and ACK stage - if ( stage != CONTROL_STAGE_SETUP ) return true; + if (stage != CONTROL_STAGE_SETUP) return true; uint8_t tmcStatusCode = USBTMC_STATUS_FAILED; #if (CFG_TUD_USBTMC_ENABLE_488) uint8_t bTag; #endif - if((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && + if ((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) && (request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) && (request->bRequest == TUSB_REQ_CLEAR_FEATURE) && - (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) - { + (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) { uint32_t ep_addr = (request->wIndex); // At this point, a transfer MAY be in progress. Based on USB spec, when clearing bulk EP HALT, // the EP transfer buffer needs to be cleared and DTOG needs to be reset, even if // the EP is not halted. The only USBD API interface to do this is to stall and then un-stall the EP. - if(ep_addr == usbtmc_state.ep_bulk_out) - { + if (ep_addr == usbtmc_state.ep_bulk_out) { criticalEnter(); - usbd_edpt_stall(rhport, (uint8_t)ep_addr); - usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr); - usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us + usbd_edpt_stall(rhport, (uint8_t) ep_addr); + usbd_edpt_clear_stall(rhport, (uint8_t) ep_addr); + usbtmc_state.state = STATE_NAK;// USBD core has placed EP in NAK state for us criticalLeave(); tud_usbtmc_bulkOut_clearFeature_cb(); - } - else if (ep_addr == usbtmc_state.ep_bulk_in) - { - usbd_edpt_stall(rhport, (uint8_t)ep_addr); - usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr); + } else if (ep_addr == usbtmc_state.ep_bulk_in) { + usbd_edpt_stall(rhport, (uint8_t) ep_addr); + usbd_edpt_clear_stall(rhport, (uint8_t) ep_addr); tud_usbtmc_bulkIn_clearFeature_cb(); - } - else if ((usbtmc_state.ep_int_in != 0) && (ep_addr == usbtmc_state.ep_int_in)) - { + } else if ((usbtmc_state.ep_int_in != 0) && (ep_addr == usbtmc_state.ep_int_in)) { // Clearing interrupt in EP - usbd_edpt_stall(rhport, (uint8_t)ep_addr); - usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr); - } - else - { + usbd_edpt_stall(rhport, (uint8_t) ep_addr); + usbd_edpt_clear_stall(rhport, (uint8_t) ep_addr); + } else { return false; } return true; } // Otherwise, we only handle class requests. - if(request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) - { + if (request->bmRequestType_bit.type != TUSB_REQ_TYPE_CLASS) { return false; } // Verification that we own the interface is unneeded since it's been routed to us specifically. - switch(request->bRequest) - { - // USBTMC required requests - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: - { - usbtmc_initiate_abort_rsp_t rsp = { - .bTag = usbtmc_state.lastBulkOutTag, - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); + switch (request->bRequest) { + // USBTMC required requests + case USBTMC_bREQUEST_INITIATE_ABORT_BULK_OUT: { + usbtmc_initiate_abort_rsp_t rsp = { + .bTag = usbtmc_state.lastBulkOutTag, + }; + TU_VERIFY(request->bmRequestType == 0xA2);// in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - // wValue is the requested bTag to abort - if(usbtmc_state.state != STATE_RCV) - { - rsp.USBTMC_status = USBTMC_STATUS_FAILED; - } - else if(usbtmc_state.lastBulkOutTag == (request->wValue & 0x7Fu)) - { - rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; - } - else - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - // Check if we've queued a short packet - criticalEnter(); - usbtmc_state.state = STATE_ABORTING_BULK_OUT; - criticalLeave(); - TU_VERIFY(tud_usbtmc_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); - usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); - } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: - { - usbtmc_check_abort_bulk_rsp_t rsp = { - .USBTMC_status = USBTMC_STATUS_SUCCESS, - .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); - TU_VERIFY(tud_usbtmc_check_abort_bulk_out_cb(&rsp)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: - { - usbtmc_initiate_abort_rsp_t rsp = { - .bTag = usbtmc_state.lastBulkInTag, - }; - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); - TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); - // wValue is the requested bTag to abort - if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) && - usbtmc_state.lastBulkInTag == (request->wValue & 0x7Fu)) - { - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.transfer_size_remaining = 0u; - // Check if we've queued a short packet - criticalEnter(); - usbtmc_state.state = ((usbtmc_state.transfer_size_sent % usbtmc_state.ep_bulk_in_wMaxPacketSize) == 0) ? - STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; - criticalLeave(); - if(usbtmc_state.transfer_size_sent == 0) - { - // Send short packet, nothing is in the buffer yet - TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin,(uint16_t)0u)); - usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; + // wValue is the requested bTag to abort + if (usbtmc_state.state != STATE_RCV) { + rsp.USBTMC_status = USBTMC_STATUS_FAILED; + } else if (usbtmc_state.lastBulkOutTag == (request->wValue & 0x7Fu)) { + rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; + } else { + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + // Check if we've queued a short packet + criticalEnter(); + usbtmc_state.state = STATE_ABORTING_BULK_OUT; + criticalLeave(); + TU_VERIFY(tud_usbtmc_initiate_abort_bulk_out_cb(&(rsp.USBTMC_status))); + usbd_edpt_stall(rhport, usbtmc_state.ep_bulk_out); } - TU_VERIFY(tud_usbtmc_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); + TU_VERIFY(tud_control_xfer(rhport, request, (void *) &rsp, sizeof(rsp))); + return true; } - else if((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) - { // FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... - rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; + + case USBTMC_bREQUEST_CHECK_ABORT_BULK_OUT_STATUS: { + usbtmc_check_abort_bulk_rsp_t rsp = { + .USBTMC_status = USBTMC_STATUS_SUCCESS, + .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent}; + TU_VERIFY(request->bmRequestType == 0xA2);// in,class,EP + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_out); + TU_VERIFY(tud_usbtmc_check_abort_bulk_out_cb(&rsp)); + TU_VERIFY(tud_control_xfer(rhport, request, (void *) &rsp, sizeof(rsp))); + return true; } - else - { - rsp.USBTMC_status = USBTMC_STATUS_FAILED; + + case USBTMC_bREQUEST_INITIATE_ABORT_BULK_IN: { + usbtmc_initiate_abort_rsp_t rsp = { + .bTag = usbtmc_state.lastBulkInTag, + }; + TU_VERIFY(request->bmRequestType == 0xA2);// in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp)); + TU_VERIFY(request->wIndex == usbtmc_state.ep_bulk_in); + // wValue is the requested bTag to abort + if ((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED) && + usbtmc_state.lastBulkInTag == (request->wValue & 0x7Fu)) { + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + usbtmc_state.transfer_size_remaining = 0u; + // Check if we've queued a short packet + criticalEnter(); + usbtmc_state.state = ((usbtmc_state.transfer_size_sent % usbtmc_state.ep_bulk_in_wMaxPacketSize) == 0) ? STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED; + criticalLeave(); + if (usbtmc_state.transfer_size_sent == 0) { + // Send short packet, nothing is in the buffer yet + TU_VERIFY(usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_epbuf.epin, (uint16_t) 0u)); + usbtmc_state.state = STATE_ABORTING_BULK_IN_SHORTED; + } + TU_VERIFY(tud_usbtmc_initiate_abort_bulk_in_cb(&(rsp.USBTMC_status))); + } else if ((usbtmc_state.state == STATE_TX_REQUESTED || usbtmc_state.state == STATE_TX_INITIATED)) {// FIXME: Unsure how to check if the OUT endpoint fifo is non-empty.... + rsp.USBTMC_status = USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS; + } else { + rsp.USBTMC_status = USBTMC_STATUS_FAILED; + } + TU_VERIFY(tud_control_xfer(rhport, request, (void *) &rsp, sizeof(rsp))); + return true; } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA2); // in,class,EP - TU_VERIFY(request->wLength == 8u); + case USBTMC_bREQUEST_CHECK_ABORT_BULK_IN_STATUS: { + TU_VERIFY(request->bmRequestType == 0xA2);// in,class,EP + TU_VERIFY(request->wLength == 8u); - usbtmc_check_abort_bulk_rsp_t rsp = - { - .USBTMC_status = USBTMC_STATUS_FAILED, - .bmAbortBulkIn = - { - .BulkInFifoBytes = (usbtmc_state.state != STATE_ABORTING_BULK_IN_ABORTED) - }, - .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, - }; - TU_VERIFY(tud_usbtmc_check_abort_bulk_in_cb(&rsp)); - criticalEnter(); - switch(usbtmc_state.state) - { - case STATE_ABORTING_BULK_IN_ABORTED: - rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; - usbtmc_state.state = STATE_IDLE; - break; - case STATE_ABORTING_BULK_IN: - case STATE_ABORTING_BULK_OUT: - rsp.USBTMC_status = USBTMC_STATUS_PENDING; - break; - default: - break; + usbtmc_check_abort_bulk_rsp_t rsp = + { + .USBTMC_status = USBTMC_STATUS_FAILED, + .bmAbortBulkIn = + { + .BulkInFifoBytes = (usbtmc_state.state != STATE_ABORTING_BULK_IN_ABORTED)}, + .NBYTES_RXD_TXD = usbtmc_state.transfer_size_sent, + }; + TU_VERIFY(tud_usbtmc_check_abort_bulk_in_cb(&rsp)); + criticalEnter(); + switch (usbtmc_state.state) { + case STATE_ABORTING_BULK_IN_ABORTED: + rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; + usbtmc_state.state = STATE_IDLE; + break; + case STATE_ABORTING_BULK_IN: + case STATE_ABORTING_BULK_OUT: + rsp.USBTMC_status = USBTMC_STATUS_PENDING; + break; + default: + break; + } + criticalLeave(); + TU_VERIFY(tud_control_xfer(rhport, request, (void *) &rsp, sizeof(rsp))); + + return true; } - criticalLeave(); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp,sizeof(rsp))); - return true; - } - - case USBTMC_bREQUEST_INITIATE_CLEAR: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + case USBTMC_bREQUEST_INITIATE_CLEAR: { + TU_VERIFY(request->bmRequestType == 0xA1);// in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); // After receiving an INITIATE_CLEAR request, the device must Halt the Bulk-OUT endpoint, queue the // control endpoint response shown in Table 31, and clear all input buffers and output buffers. @@ -834,112 +758,97 @@ bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request usbtmc_state.state = STATE_CLEARING; criticalLeave(); TU_VERIFY(tud_usbtmc_initiate_clear_cb(&tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode,sizeof(tmcStatusCode))); + TU_VERIFY(tud_control_xfer(rhport, request, (void *) &tmcStatusCode, sizeof(tmcStatusCode))); return true; } - case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + case USBTMC_bREQUEST_CHECK_CLEAR_STATUS: { + TU_VERIFY(request->bmRequestType == 0xA1);// in,class,interface usbtmc_get_clear_status_rsp_t clearStatusRsp = {0}; TU_VERIFY(request->wLength == sizeof(clearStatusRsp)); - if(usbd_edpt_busy(rhport, usbtmc_state.ep_bulk_in)) - { + if (usbd_edpt_busy(rhport, usbtmc_state.ep_bulk_in)) { // Stuff stuck in TX buffer? clearStatusRsp.bmClear.BulkInFifoBytes = 1; clearStatusRsp.USBTMC_status = USBTMC_STATUS_PENDING; - } - else - { + } else { // Let app check if it's clear TU_VERIFY(tud_usbtmc_check_clear_cb(&clearStatusRsp)); } - if(clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) - { + if (clearStatusRsp.USBTMC_status == USBTMC_STATUS_SUCCESS) { criticalEnter(); usbtmc_state.state = STATE_IDLE; criticalLeave(); } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&clearStatusRsp,sizeof(clearStatusRsp))); + TU_VERIFY(tud_control_xfer(rhport, request, (void *) &clearStatusRsp, sizeof(clearStatusRsp))); return true; } - case USBTMC_bREQUEST_GET_CAPABILITIES: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + case USBTMC_bREQUEST_GET_CAPABILITIES: { + TU_VERIFY(request->bmRequestType == 0xA1);// in,class,interface TU_VERIFY(request->wLength == sizeof(*(usbtmc_state.capabilities))); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)(uintptr_t) usbtmc_state.capabilities, sizeof(*usbtmc_state.capabilities))); + TU_VERIFY(tud_control_xfer(rhport, request, (void *) (uintptr_t) usbtmc_state.capabilities, sizeof(*usbtmc_state.capabilities))); return true; } - // USBTMC Optional Requests + // USBTMC Optional Requests - case USBTMC_bREQUEST_INDICATOR_PULSE: // Optional + case USBTMC_bREQUEST_INDICATOR_PULSE:// Optional { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + TU_VERIFY(request->bmRequestType == 0xA1);// in,class,interface TU_VERIFY(request->wLength == sizeof(tmcStatusCode)); TU_VERIFY(usbtmc_state.capabilities->bmIntfcCapabilities.supportsIndicatorPulse); TU_VERIFY(tud_usbtmc_indicator_pulse_cb(request, &tmcStatusCode)); - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&tmcStatusCode, sizeof(tmcStatusCode))); + TU_VERIFY(tud_control_xfer(rhport, request, (void *) &tmcStatusCode, sizeof(tmcStatusCode))); return true; } #if (CFG_TUD_USBTMC_ENABLE_488) - // USB488 required requests - case USB488_bREQUEST_READ_STATUS_BYTE: - { + // USB488 required requests + case USB488_bREQUEST_READ_STATUS_BYTE: { usbtmc_read_stb_rsp_488_t rsp; TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface - TU_VERIFY(request->wLength == sizeof(rsp)); // in,class,interface + TU_VERIFY(request->wLength == sizeof(rsp));// in,class,interface bTag = request->wValue & 0x7F; TU_VERIFY(request->bmRequestType == 0xA1); - TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero (USB488v1.0 Table 11) + TU_VERIFY((request->wValue & (~0x7F)) == 0u);// Other bits are required to be zero (USB488v1.0 Table 11) TU_VERIFY(bTag >= 0x02 && bTag <= 127); TU_VERIFY(request->wIndex == usbtmc_state.itf_id); TU_VERIFY(request->wLength == 0x0003); - rsp.bTag = (uint8_t)bTag; - if(usbtmc_state.ep_int_in != 0) - { - rsp.statusByte = 0x00; // Use interrupt endpoint, instead. Must be 0x00 (USB488v1.0 4.3.1.2) - if(usbd_edpt_busy(rhport, usbtmc_state.ep_int_in)) - { + rsp.bTag = (uint8_t) bTag; + if (usbtmc_state.ep_int_in != 0) { + rsp.statusByte = 0x00;// Use interrupt endpoint, instead. Must be 0x00 (USB488v1.0 4.3.1.2) + if (usbd_edpt_busy(rhport, usbtmc_state.ep_int_in)) { rsp.USBTMC_status = USB488_STATUS_INTERRUPT_IN_BUSY; - } - else - { + } else { rsp.USBTMC_status = USBTMC_STATUS_SUCCESS; usbtmc_read_stb_interrupt_488_t intMsg = - { - .bNotify1 = { - .one = 1, - .bTag = bTag & 0x7Fu, - }, - .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)) - }; + { + .bNotify1 = { + .one = 1, + .bTag = bTag & 0x7Fu, + }, + .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status))}; // Must be queued before control request response sent (USB488v1.0 4.3.1.2) - usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg)); + usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void *) &intMsg, sizeof(intMsg)); } - } - else - { + } else { rsp.statusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status)); } - TU_VERIFY(tud_control_xfer(rhport, request, (void*)&rsp, sizeof(rsp))); + TU_VERIFY(tud_control_xfer(rhport, request, (void *) &rsp, sizeof(rsp))); return true; } - // USB488 optional requests - case USB488_bREQUEST_REN_CONTROL: - case USB488_bREQUEST_GO_TO_LOCAL: - case USB488_bREQUEST_LOCAL_LOCKOUT: - { - TU_VERIFY(request->bmRequestType == 0xA1); // in,class,interface + // USB488 optional requests + case USB488_bREQUEST_REN_CONTROL: + case USB488_bREQUEST_GO_TO_LOCAL: + case USB488_bREQUEST_LOCAL_LOCKOUT: { + TU_VERIFY(request->bmRequestType == 0xA1);// in,class,interface return false; } #endif - default: - return false; + default: + return false; } } From d533650105c3d41e77a063869175cc56f5ef0461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Berger?= Date: Mon, 9 Jun 2025 16:56:02 +0200 Subject: [PATCH 208/382] Fix TUH_EPSIZE_BULK_MPS macro TUH_EPSIZE_BULK_MPS should be set based on TUH_OPT_HIGH_SPEED, not TUD_OPT_HIGH_SPEED --- src/host/usbh.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/host/usbh.h b/src/host/usbh.h index 6f34d8bb3..13eede869 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -42,7 +42,7 @@ //--------------------------------------------------------------------+ // Endpoint Bulk size depending on host mx speed -#define TUH_EPSIZE_BULK_MPS (TUD_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) +#define TUH_EPSIZE_BULK_MPS (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) // forward declaration struct tuh_xfer_s; From b56265f38182b71e39179a88ddaeca4786e6b780 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 10 Jun 2025 22:28:03 +0700 Subject: [PATCH 209/382] merge all maxim (32650, 32666, 32690, 78002) family into common bsp/maxim. Only support cmake build system rename hw/mcu/analog/max32 to hw/mcu/analog/msdk --- .github/workflows/ci_set_matrix.py | 2 +- hw/bsp/espressif/family.cmake | 2 - hw/bsp/family_support.cmake | 16 +- hw/bsp/max32650/README.md | 46 ---- .../max32650/boards/max32650evkit/board.cmake | 10 - hw/bsp/max32650/boards/max32650evkit/board.mk | 2 - .../max32650/boards/max32650fthr/board.cmake | 10 - hw/bsp/max32650/boards/max32650fthr/board.mk | 2 - .../max32650/boards/max32650fthr/max32650.ld | 119 ---------- hw/bsp/max32650/boards/max32651evkit/board.mk | 5 - hw/bsp/max32650/family.c | 177 --------------- hw/bsp/max32650/family.cmake | 169 --------------- hw/bsp/max32650/family.mk | 140 ------------ .../max32666/FreeRTOSConfig/FreeRTOSConfig.h | 149 ------------- hw/bsp/max32666/README.md | 32 --- .../max32666/boards/max32666evkit/board.cmake | 1 - hw/bsp/max32666/boards/max32666evkit/board.mk | 1 - .../max32666/boards/max32666fthr/board.cmake | 1 - hw/bsp/max32666/boards/max32666fthr/board.mk | 1 - hw/bsp/max32666/family.cmake | 147 ------------- hw/bsp/max32666/family.mk | 93 -------- .../max32690/FreeRTOSConfig/FreeRTOSConfig.h | 149 ------------- hw/bsp/max32690/README.md | 31 --- hw/bsp/max32690/boards/apard32690/board.cmake | 1 - hw/bsp/max32690/boards/apard32690/board.mk | 1 - .../max32690/boards/max32690evkit/board.cmake | 1 - hw/bsp/max32690/boards/max32690evkit/board.mk | 1 - hw/bsp/max32690/family.c | 175 --------------- hw/bsp/max32690/family.cmake | 152 ------------- hw/bsp/max32690/family.mk | 101 --------- .../max78002/FreeRTOSConfig/FreeRTOSConfig.h | 149 ------------- hw/bsp/max78002/README.md | 28 --- .../max78002/boards/max78002evkit/board.cmake | 1 - hw/bsp/max78002/boards/max78002evkit/board.mk | 1 - hw/bsp/max78002/family.c | 173 --------------- hw/bsp/max78002/family.cmake | 166 -------------- hw/bsp/max78002/family.mk | 99 --------- .../FreeRTOSConfig/FreeRTOSConfig.h | 0 hw/bsp/maxim/README.md | 43 ++++ hw/bsp/maxim/boards/apard32690/board.cmake | 4 + .../boards/apard32690/board.h | 0 hw/bsp/maxim/boards/max32650evkit/board.cmake | 8 + .../boards/max32650evkit/board.h | 0 hw/bsp/maxim/boards/max32650fthr/board.cmake | 8 + .../boards/max32650fthr/board.h | 0 .../boards/max32651evkit/board.cmake | 15 +- .../boards/max32651evkit/board.h | 0 hw/bsp/maxim/boards/max32666evkit/board.cmake | 4 + .../boards/max32666evkit/board.h | 0 hw/bsp/maxim/boards/max32666fthr/board.cmake | 4 + .../boards/max32666fthr/board.h | 0 hw/bsp/maxim/boards/max32690evkit/board.cmake | 4 + .../boards/max32690evkit/board.h | 0 hw/bsp/maxim/boards/max78002evkit/board.cmake | 4 + .../boards/max78002evkit/board.h | 0 hw/bsp/{max32666 => maxim}/family.c | 48 +++- hw/bsp/maxim/family.cmake | 205 ++++++++++++++++++ .../linker}/max32650.ld | 0 .../linker}/max32651.ld | 0 .../max32666.ld => maxim/linker/max32665.ld} | 0 hw/bsp/{max32690 => maxim/linker}/max32690.ld | 0 hw/bsp/{max78002 => maxim/linker}/max78002.ld | 0 tools/get_deps.py | 4 +- 63 files changed, 348 insertions(+), 2357 deletions(-) delete mode 100644 hw/bsp/max32650/README.md delete mode 100644 hw/bsp/max32650/boards/max32650evkit/board.cmake delete mode 100644 hw/bsp/max32650/boards/max32650evkit/board.mk delete mode 100644 hw/bsp/max32650/boards/max32650fthr/board.cmake delete mode 100644 hw/bsp/max32650/boards/max32650fthr/board.mk delete mode 100644 hw/bsp/max32650/boards/max32650fthr/max32650.ld delete mode 100644 hw/bsp/max32650/boards/max32651evkit/board.mk delete mode 100644 hw/bsp/max32650/family.c delete mode 100644 hw/bsp/max32650/family.cmake delete mode 100644 hw/bsp/max32650/family.mk delete mode 100644 hw/bsp/max32666/FreeRTOSConfig/FreeRTOSConfig.h delete mode 100644 hw/bsp/max32666/README.md delete mode 100644 hw/bsp/max32666/boards/max32666evkit/board.cmake delete mode 100644 hw/bsp/max32666/boards/max32666evkit/board.mk delete mode 100644 hw/bsp/max32666/boards/max32666fthr/board.cmake delete mode 100644 hw/bsp/max32666/boards/max32666fthr/board.mk delete mode 100644 hw/bsp/max32666/family.cmake delete mode 100644 hw/bsp/max32666/family.mk delete mode 100644 hw/bsp/max32690/FreeRTOSConfig/FreeRTOSConfig.h delete mode 100644 hw/bsp/max32690/README.md delete mode 100644 hw/bsp/max32690/boards/apard32690/board.cmake delete mode 100644 hw/bsp/max32690/boards/apard32690/board.mk delete mode 100644 hw/bsp/max32690/boards/max32690evkit/board.cmake delete mode 100644 hw/bsp/max32690/boards/max32690evkit/board.mk delete mode 100644 hw/bsp/max32690/family.c delete mode 100644 hw/bsp/max32690/family.cmake delete mode 100644 hw/bsp/max32690/family.mk delete mode 100644 hw/bsp/max78002/FreeRTOSConfig/FreeRTOSConfig.h delete mode 100644 hw/bsp/max78002/README.md delete mode 100644 hw/bsp/max78002/boards/max78002evkit/board.cmake delete mode 100644 hw/bsp/max78002/boards/max78002evkit/board.mk delete mode 100644 hw/bsp/max78002/family.c delete mode 100644 hw/bsp/max78002/family.cmake delete mode 100644 hw/bsp/max78002/family.mk rename hw/bsp/{max32650 => maxim}/FreeRTOSConfig/FreeRTOSConfig.h (100%) create mode 100644 hw/bsp/maxim/README.md create mode 100644 hw/bsp/maxim/boards/apard32690/board.cmake rename hw/bsp/{max32690 => maxim}/boards/apard32690/board.h (100%) create mode 100644 hw/bsp/maxim/boards/max32650evkit/board.cmake rename hw/bsp/{max32650 => maxim}/boards/max32650evkit/board.h (100%) create mode 100644 hw/bsp/maxim/boards/max32650fthr/board.cmake rename hw/bsp/{max32650 => maxim}/boards/max32650fthr/board.h (100%) rename hw/bsp/{max32650 => maxim}/boards/max32651evkit/board.cmake (81%) rename hw/bsp/{max32650 => maxim}/boards/max32651evkit/board.h (100%) create mode 100644 hw/bsp/maxim/boards/max32666evkit/board.cmake rename hw/bsp/{max32666 => maxim}/boards/max32666evkit/board.h (100%) create mode 100644 hw/bsp/maxim/boards/max32666fthr/board.cmake rename hw/bsp/{max32666 => maxim}/boards/max32666fthr/board.h (100%) create mode 100644 hw/bsp/maxim/boards/max32690evkit/board.cmake rename hw/bsp/{max32690 => maxim}/boards/max32690evkit/board.h (100%) create mode 100644 hw/bsp/maxim/boards/max78002evkit/board.cmake rename hw/bsp/{max78002 => maxim}/boards/max78002evkit/board.h (100%) rename hw/bsp/{max32666 => maxim}/family.c (77%) create mode 100644 hw/bsp/maxim/family.cmake rename hw/bsp/{max32650/boards/max32650evkit => maxim/linker}/max32650.ld (100%) rename hw/bsp/{max32650/boards/max32651evkit => maxim/linker}/max32651.ld (100%) rename hw/bsp/{max32666/max32666.ld => maxim/linker/max32665.ld} (100%) rename hw/bsp/{max32690 => maxim/linker}/max32690.ld (100%) rename hw/bsp/{max78002 => maxim/linker}/max78002.ld (100%) diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index fa73dc1b6..bccb07e3e 100755 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -24,7 +24,7 @@ family_list = { "lpc11 lpc13 lpc15": ["arm-gcc", "arm-clang"], "lpc17 lpc18 lpc40 lpc43": ["arm-gcc", "arm-clang"], "lpc51 lpc54 lpc55": ["arm-gcc", "arm-clang"], - "max32650 max32666 max32690 max78002": ["arm-gcc"], + "maxim": ["arm-gcc"], "mcx": ["arm-gcc"], "mm32": ["arm-gcc"], "msp430": ["msp430-gcc"], diff --git a/hw/bsp/espressif/family.cmake b/hw/bsp/espressif/family.cmake index b544689d9..2aad7d185 100644 --- a/hw/bsp/espressif/family.cmake +++ b/hw/bsp/espressif/family.cmake @@ -32,8 +32,6 @@ endif () # Add example src and bsp directories set(EXTRA_COMPONENT_DIRS "src" "${CMAKE_CURRENT_LIST_DIR}/boards" "${CMAKE_CURRENT_LIST_DIR}/components") - -# set SDKCONFIG for each IDF Target set(SDKCONFIG ${CMAKE_BINARY_DIR}/sdkconfig) include($ENV{IDF_PATH}/tools/cmake/project.cmake) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 3a6890690..ac1276f7d 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -482,7 +482,7 @@ function(family_flash_openocd TARGET) # note skip verify since it has issue with rp2040 add_custom_target(${TARGET}-openocd DEPENDS ${TARGET} - COMMAND ${OPENOCD} -c "tcl_port disabled" -c "gdb_port disabled" ${OPTION_LIST} -c init -c halt -c "program $" -c reset ${OPTION_LIST2} -c exit + COMMAND ${OPENOCD} -c "tcl_port disabled; gdb_port disabled" ${OPTION_LIST} -c "init; halt; program $" -c reset ${OPTION_LIST2} -c exit VERBATIM ) endfunction() @@ -502,10 +502,16 @@ endfunction() # Add flash openocd adi (Analog Devices) target # included with msdk or compiled from release branch of https://github.com/analogdevicesinc/openocd function(family_flash_openocd_adi TARGET) - if (DEFINED $ENV{MAXIM_PATH}) - # use openocd from msdk - set(OPENOCD ENV{MAXIM_PATH}/Tools/OpenOCD/openocd) - set(OPENOCD_OPTION2 "-s ENV{MAXIM_PATH}/Tools/OpenOCD/scripts") + if (DEFINED MAXIM_PATH) + # use openocd from msdk with MAXIM_PATH cmake variable first if the user specified it + set(OPENOCD ${MAXIM_PATH}/Tools/OpenOCD/openocd) + set(OPENOCD_OPTION2 "-s ${MAXIM_PATH}/Tools/OpenOCD/scripts") + elseif (DEFINED ENV{MAXIM_PATH}) + # use openocd from msdk with MAXIM_PATH environment variable. Normalize + # since msdk can be Windows (MinGW) or Linux + file(TO_CMAKE_PATH "$ENV{MAXIM_PATH}" MAXIM_PATH_NORM) + set(OPENOCD ${MAXIM_PATH_NORM}/Tools/OpenOCD/openocd) + set(OPENOCD_OPTION2 "-s ${MAXIM_PATH_NORM}/Tools/OpenOCD/scripts") else() # compiled from source if (NOT DEFINED OPENOCD_ADI_PATH) diff --git a/hw/bsp/max32650/README.md b/hw/bsp/max32650/README.md deleted file mode 100644 index ca66a1ac4..000000000 --- a/hw/bsp/max32650/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# Analog Devices MAX32650/1/2 - -This BSP is for working with the Analog Devices -[MAX32650](https://www.analog.com/en/products/max32650.html), -[MAX32651](https://www.analog.com/en/products/max32651.html) and -[MAX32652](https://www.analog.com/en/products/max32652.html) -microcontrollers. The following boards are supported: - * [MAX32650EVKIT](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/max32650-evkit.html) - * [MAX32650FTHR](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/max32650fthr.html) - * [MAX32651EVKIT](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/max32651-evkit.html) (Secure Bootloader) - -This part family leverages the Maxim Microcontrollers SDK (MSDK) for the device -interfaces and hardware abstraction layers. This source code package is fetched -as part of the get-deps script. - -The microcontrollers utilize the standard GNU ARM toolchain. If this toolchain -is not already available on your build machine, it can be installed by using the -bundled MSDK installation. Details on downloading and installing can be found -in the [User's Guide](https://analogdevicesinc.github.io/msdk//USERGUIDE/). - -## Flashing - -### MAX32650 and MAX32652 - -The default flashing behavior in this BSP for the MAX32650 and MAX32652 is to -utilize JLink. This can be done by running the `flash` or `flash-jlink` rule -for Makefiles, or the `-jlink` target for CMake. - -Both the Evaluation Kit and Feather boards are shipped with a CMSIS-DAP -compatible debug probe. However, at the time of writing, the necessary flashing -algorithms for OpenOCD have not yet been incorporated into the OpenOCD master -branch. To utilize the provided debug probes, please install the bundled MSDK -package which includes the appropriate OpenOCD modifications. To leverage this -OpenOCD instance, run the `flash-msdk` Makefile rule, or `-msdk` CMake -target. - -### MAX32651 - -The MAX32651 features an integrated secure bootloader which requires the -application image be signed prior to flashing. Both the Makefile and CMake -scripts account for this signing automatically when building for the -MAX32651EVKIT. - -To flash the signed image, the MSDK's OpenOCD variant must be used. To flash -the MAX32651EVKIT please install the bundled MSDK, and utilize the `flash-msdk` -and `-msdk` rule and target. diff --git a/hw/bsp/max32650/boards/max32650evkit/board.cmake b/hw/bsp/max32650/boards/max32650evkit/board.cmake deleted file mode 100644 index fffdcc9fb..000000000 --- a/hw/bsp/max32650/boards/max32650evkit/board.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# Use the standard, non-secure linker file -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/max32650.ld) - -function(update_board_extras TARGET) - #No extra arguments -endfunction() - -function(prepare_image TARGET_IN) - #No signing required -endfunction() diff --git a/hw/bsp/max32650/boards/max32650evkit/board.mk b/hw/bsp/max32650/boards/max32650evkit/board.mk deleted file mode 100644 index 0bc210e11..000000000 --- a/hw/bsp/max32650/boards/max32650evkit/board.mk +++ /dev/null @@ -1,2 +0,0 @@ -# Use the standard, non-secure linker file -LD_FILE = $(BOARD_PATH)/max32650.ld diff --git a/hw/bsp/max32650/boards/max32650fthr/board.cmake b/hw/bsp/max32650/boards/max32650fthr/board.cmake deleted file mode 100644 index fffdcc9fb..000000000 --- a/hw/bsp/max32650/boards/max32650fthr/board.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# Use the standard, non-secure linker file -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/max32650.ld) - -function(update_board_extras TARGET) - #No extra arguments -endfunction() - -function(prepare_image TARGET_IN) - #No signing required -endfunction() diff --git a/hw/bsp/max32650/boards/max32650fthr/board.mk b/hw/bsp/max32650/boards/max32650fthr/board.mk deleted file mode 100644 index 0bc210e11..000000000 --- a/hw/bsp/max32650/boards/max32650fthr/board.mk +++ /dev/null @@ -1,2 +0,0 @@ -# Use the standard, non-secure linker file -LD_FILE = $(BOARD_PATH)/max32650.ld diff --git a/hw/bsp/max32650/boards/max32650fthr/max32650.ld b/hw/bsp/max32650/boards/max32650fthr/max32650.ld deleted file mode 100644 index 0e56a91ec..000000000 --- a/hw/bsp/max32650/boards/max32650fthr/max32650.ld +++ /dev/null @@ -1,119 +0,0 @@ -MEMORY { - ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x00010000 /* 64kB ROM */ - FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 0x00300000 /* 3MB flash */ - SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00100000 /* 1MB SRAM */ -} - -SECTIONS { - .text : - { - _text = .; - KEEP(*(.isr_vector)) - *(.text*) /* program code */ - *(.rodata*) /* read-only data: "const" */ - - KEEP(*(.init)) - KEEP(*(.fini)) - - /* .ctors */ - *crtbegin.o(.ctors) - *crtbegin?.o(.ctors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) - *(SORT(.ctors.*)) - *(.ctors) - - /* .dtors */ - *crtbegin.o(.dtors) - *crtbegin?.o(.dtors) - *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) - *(SORT(.dtors.*)) - *(.dtors) - - /* C++ Exception handling */ - KEEP(*(.eh_frame*)) - _etext = .; - } > FLASH - - .ARM.extab : - { - *(.ARM.extab* .gnu.linkonce.armextab.*) - } > FLASH - - /* it's used for C++ exception handling */ - /* we need to keep this to avoid overlapping */ - .ARM.exidx : - { - __exidx_start = .; - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - __exidx_end = .; - } > FLASH - - .data : - { - _data = ALIGN(., 4); - *(vtable) - *(.data*) /*read-write initialized data: initialized global variable*/ - *(.spix_config*) /* SPIX configuration functions need to be run from SRAM */ - *(.flashprog*) /* Flash program */ - - - /* These array sections are used by __libc_init_array to call static C++ constructors */ - . = ALIGN(4); - /* preinit data */ - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP(*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - - . = ALIGN(4); - /* init data */ - PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) - KEEP(*(.init_array)) - PROVIDE_HIDDEN (__init_array_end = .); - - . = ALIGN(4); - /* finit data */ - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP(*(SORT(.fini_array.*))) - KEEP(*(.fini_array)) - PROVIDE_HIDDEN (__fini_array_end = .); - - _edata = ALIGN(., 4); - } > SRAM AT>FLASH - __load_data = LOADADDR(.data); - .bss : - { - . = ALIGN(4); - _bss = .; - *(.bss*) /*read-write zero initialized data: uninitialized global variable*/ - *(COMMON) - _ebss = ALIGN(., 4); - } > SRAM - - /* Set stack top to end of RAM, and stack limit move down by - * size of stack_dummy section */ - __StackTop = ORIGIN(SRAM) + LENGTH(SRAM); - __StackLimit = __StackTop - SIZEOF(.stack_dummy); - - /* .stack_dummy section doesn't contains any symbols. It is only - * used for linker to calculate size of stack sections, and assign - * values to stack symbols later */ - .stack_dummy (COPY): - { - *(.stack*) - } > SRAM - - .heap (COPY): - { - . = ALIGN(4); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - *(.heap*) - __HeapLimit = ABSOLUTE(__StackLimit); - } > SRAM - - PROVIDE(__stack = __StackTop); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= _ebss, "region RAM overflowed with stack") -} diff --git a/hw/bsp/max32650/boards/max32651evkit/board.mk b/hw/bsp/max32650/boards/max32651evkit/board.mk deleted file mode 100644 index b609598c1..000000000 --- a/hw/bsp/max32650/boards/max32651evkit/board.mk +++ /dev/null @@ -1,5 +0,0 @@ -# Use the secure linker file -LD_FILE = $(BOARD_PATH)/max32651.ld - -# Let the family script know the build needs to be signed -SIGNED_BUILD := 1 diff --git a/hw/bsp/max32650/family.c b/hw/bsp/max32650/family.c deleted file mode 100644 index 8f0e56734..000000000 --- a/hw/bsp/max32650/family.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 Brent Kowal (Analog Devices, Inc) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/* metadata: - manufacturer: Analog Devices -*/ - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-prototypes" // _mxc_crit_get_state() -#endif - -#include "gpio.h" -#include "mxc_sys.h" -#include "mxc_device.h" -#include "uart.h" - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - -#include "board.h" -#include "bsp/board_api.h" - - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USB_IRQHandler(void) { - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ -mxc_uart_regs_t *ConsoleUart = MXC_UART_GET_UART(UART_NUM); - -void board_init(void) { -#if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer - SysTick_Config(SystemCoreClock / 1000); -#elif CFG_TUSB_OS == OPT_OS_FREERTOS - // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); -#endif - mxc_gpio_cfg_t gpioConfig; - - // LED - gpioConfig.drvstr = MXC_GPIO_DRVSTR_0; - gpioConfig.func = MXC_GPIO_FUNC_OUT; - gpioConfig.mask = LED_PIN; - gpioConfig.pad = MXC_GPIO_PAD_NONE; - gpioConfig.port = LED_PORT; - gpioConfig.vssel = LED_VDDIO; - MXC_GPIO_Config(&gpioConfig); - board_led_write(false); - - // Button - gpioConfig.drvstr = MXC_GPIO_DRVSTR_0; - gpioConfig.func = MXC_GPIO_FUNC_IN; - gpioConfig.mask = BUTTON_PIN; - gpioConfig.pad = BUTTON_PULL; - gpioConfig.port = BUTTON_PORT; - gpioConfig.vssel = MXC_GPIO_VSSEL_VDDIO; - MXC_GPIO_Config(&gpioConfig); - - // UART - MXC_UART_Init(ConsoleUart, CFG_BOARD_UART_BAUDRATE); - - //USB - // Startup the HIRC96M clock if it's not on already - if (!(MXC_GCR->clk_ctrl & MXC_F_GCR_CLK_CTRL_HIRC96_EN)) { - MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_HIRC96_EN; - MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_HIRC96_RDY); - } - - MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); - MXC_SYS_Reset_Periph(MXC_SYS_RESET_USB); -} - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) { -#if LED_STATE_ON - state = !state; -#endif - if (state) { - MXC_GPIO_OutClr(LED_PORT, LED_PIN); - } else { - MXC_GPIO_OutSet(LED_PORT, LED_PIN); - } -} - -uint32_t board_button_read(void) { - uint32_t state = MXC_GPIO_InGet(BUTTON_PORT, BUTTON_PIN) ? 1 : 0; - return BUTTON_STATE_ACTIVE == state; -} - -size_t board_get_unique_id(uint8_t id[], size_t max_len) { - uint8_t hw_id[13];//USN Buffer - MXC_SYS_GetUSN(hw_id, 13); - - size_t act_len = TU_MIN(max_len, 13); - memcpy(id, hw_id, act_len); - return act_len; -} - -int board_uart_read(uint8_t *buf, int len) { - int uart_val; - int act_len = 0; - - while (act_len < len) { - if ((uart_val = MXC_UART_ReadCharacterRaw(ConsoleUart)) == E_UNDERFLOW) { - break; - } else { - *buf++ = (uint8_t) uart_val; - act_len++; - } - } - return act_len; -} - -int board_uart_write(void const *buf, int len) { - int act_len = 0; - const uint8_t *ch_ptr = (const uint8_t *) buf; - while (act_len < len) { - MXC_UART_WriteCharacter(ConsoleUart, *ch_ptr++); - act_len++; - } - return len; -} - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; - -void SysTick_Handler(void) { - system_ticks++; -} - -uint32_t board_millis(void) { - return system_ticks; -} -#endif - -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) { -} diff --git a/hw/bsp/max32650/family.cmake b/hw/bsp/max32650/family.cmake deleted file mode 100644 index b1d5dded7..000000000 --- a/hw/bsp/max32650/family.cmake +++ /dev/null @@ -1,169 +0,0 @@ -include_guard() - -set(MAX32_PERIPH ${TOP}/hw/mcu/analog/max32/Libraries/PeriphDrivers) -set(MAX32_CMSIS ${TOP}/hw/mcu/analog/max32/Libraries/CMSIS) -set(CMSIS_5 ${TOP}/lib/CMSIS_5) - -# include board specific information and functions -include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) - -# Get the linker file -set(LD_FILE_Clang ${LD_FILE_GNU}) - -# toolchain set up -set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") -set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) -set(JLINK_DEVICE max32650) -set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -f target/max32650.cfg") - -set(FAMILY_MCUS MAX32650 CACHE INTERNAL "") - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - TARGET=MAX32650 - TARGET_REV=0x4131 - MXC_ASSERT_ENABLE - MAX32650 - IAR_PRAGMAS=0 - CFG_TUSB_MCU=OPT_MCU_MAX32650 - BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - ) - - # Run any board specific updates - update_board_extras(${TARGET}) -endfunction() - -#------------------------------------ -# BOARD_TARGET -#------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${MAX32_CMSIS}/Device/Maxim/MAX32650/Source/GCC/startup_max32650.S) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - - set(PERIPH_SRC ${MAX32_PERIPH}/Source) - add_library(${BOARD_TARGET} STATIC - ${MAX32_CMSIS}/Device/Maxim/MAX32650/Source/heap.c - ${MAX32_CMSIS}/Device/Maxim/MAX32650/Source/header_MAX32650.c - ${MAX32_CMSIS}/Device/Maxim/MAX32650/Source/system_max32650.c - ${PERIPH_SRC}/SYS/mxc_assert.c - ${PERIPH_SRC}/SYS/mxc_delay.c - ${PERIPH_SRC}/SYS/mxc_lock.c - ${PERIPH_SRC}/SYS/nvic_table.c - ${PERIPH_SRC}/SYS/pins_me10.c - ${PERIPH_SRC}/SYS/sys_me10.c - ${PERIPH_SRC}/TPU/tpu_me10.c - ${PERIPH_SRC}/TPU/tpu_reva.c - ${PERIPH_SRC}/FLC/flc_common.c - ${PERIPH_SRC}/FLC/flc_me10.c - ${PERIPH_SRC}/FLC/flc_reva.c - ${PERIPH_SRC}/GPIO/gpio_common.c - ${PERIPH_SRC}/GPIO/gpio_me10.c - ${PERIPH_SRC}/GPIO/gpio_reva.c - ${PERIPH_SRC}/ICC/icc_me10.c - ${PERIPH_SRC}/ICC/icc_reva.c - ${PERIPH_SRC}/ICC/icc_common.c - ${PERIPH_SRC}/UART/uart_common.c - ${PERIPH_SRC}/UART/uart_me10.c - ${PERIPH_SRC}/UART/uart_reva.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${MAX32_CMSIS}/Include - ${MAX32_CMSIS}/Device/Maxim/MAX32650/Include - ${MAX32_PERIPH}/Include/MAX32650 - ${PERIPH_SRC}/SYS - ${PERIPH_SRC}/GPIO - ${PERIPH_SRC}/TPU - ${PERIPH_SRC}/ICC - ${PERIPH_SRC}/FLC - ${PERIPH_SRC}/UART - ) - - target_compile_options(${BOARD_TARGET} PRIVATE - -Wno-error=strict-prototypes - ) - update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - -u sb_header #Needed when linking libraries to not lose the Signing header - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - endif () -endfunction() - - -#------------------------------------ -# Functions -#------------------------------------ -function(family_configure_example TARGET RTOS) - family_configure_common(${TARGET} ${RTOS}) - - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h - target_sources(${TARGET} PUBLIC - # BSP - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ) - target_include_directories(${TARGET} PUBLIC - # family, hw, board - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} - ) - - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_MAX32650) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/mentor/musb/dcd_musb.c - ) - target_compile_options(${TARGET} PRIVATE - -Wno-error=strict-prototypes - ) - - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - target_compile_options(${TARGET} PRIVATE - -Wno-error=strict-prototypes - ) - - - - # Flashing - family_add_bin_hex(${TARGET}) - family_flash_jlink(${TARGET}) - family_flash_openocd_adi(${TARGET}) - - # Add the optional MSDK OpenOCD flashing - family_flash_msdk(${TARGET}) -endfunction() - -function(family_flash_msdk TARGET) - # Prepare the image (signed) if the board requires it - prepare_image(${TARGET}) - - set(MAXIM_PATH "$ENV{MAXIM_PATH}") - add_custom_target(${TARGET}-msdk - DEPENDS ${TARGET} - COMMAND ${MAXIM_PATH}/Tools/OpenOCD/openocd -s ${MAXIM_PATH}/Tools/OpenOCD/scripts - -f interface/cmsis-dap.cfg -f target/max32650.cfg - -c "program $ verify; init; reset; exit" - VERBATIM - ) -endfunction() diff --git a/hw/bsp/max32650/family.mk b/hw/bsp/max32650/family.mk deleted file mode 100644 index d2fc293e4..000000000 --- a/hw/bsp/max32650/family.mk +++ /dev/null @@ -1,140 +0,0 @@ -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/analog/max32 - -# Important locations in the hw support for MCU -MAX32_CMSIS = hw/mcu/analog/max32/Libraries/CMSIS -MAX32_PERIPH = hw/mcu/analog/max32/Libraries/PeriphDrivers - -# Add any board specific make rules -include $(TOP)/$(BOARD_PATH)/board.mk - -CPU_CORE ?= cortex-m4 -PORT ?= 0 - -# GCC -SRC_S_GCC += $(MAX32_CMSIS)/Device/Maxim/MAX32650/Source/GCC/startup_max32650.S - -# -------------- -# Compiler Flags -# -------------- -# Flags for the MAX32650/1/2 SDK -CFLAGS += -DTARGET=MAX32650 \ - -DTARGET_REV=0x4131 \ - -DMXC_ASSERT_ENABLE \ - -DMAX32650 \ - -DIAR_PRAGMAS=0 - -# Flags for TUSB features -CFLAGS += \ - -DCFG_TUSB_MCU=OPT_MCU_MAX32650 \ - -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - -# mcu driver cause following warnings -CFLAGS += -Wno-error=strict-prototypes \ - -Wno-error=unused-parameter \ - -Wno-error=cast-align \ - -Wno-error=cast-qual \ - -Wno-error=sign-compare - -LDFLAGS_GCC += -nostartfiles --specs=nosys.specs --specs=nano.specs - -# Configure the flash rule. By default, use JLink. -SIGNED_BUILD ?= 0 -DEFAULT_FLASH = flash-jlink - -# If the applications needs to be signed (for the MAX32651), sign it first and -# then need to use MSDK's OpenOCD to flash it -# Also need to include the __SLA_FWK__ define to enable the signed header into -# memory -ifeq ($(SIGNED_BUILD), 1) -# Extra definitions to build for the secure part -CFLAGS += -D__SLA_FWK__ -DEFAULT_FLASH := sign-build flash-msdk -endif - -# For flash-jlink target -JLINK_DEVICE = max32650 - -# Configure the flash rule -flash: $(DEFAULT_FLASH) - -# ----------------- -# Sources & Include -# ----------------- -PERIPH_SRC = $(TOP)/$(MAX32_PERIPH)/Source -SRC_C += \ - src/portable/mentor/musb/dcd_musb.c \ - $(MAX32_CMSIS)/Device/Maxim/MAX32650/Source/heap.c \ - $(MAX32_CMSIS)/Device/Maxim/MAX32650/Source/system_max32650.c \ - $(MAX32_CMSIS)/Device/Maxim/MAX32650/Source/header_MAX32650.c \ - $(PERIPH_SRC)/SYS/mxc_assert.c \ - $(PERIPH_SRC)/SYS/mxc_delay.c \ - $(PERIPH_SRC)/SYS/mxc_lock.c \ - $(PERIPH_SRC)/SYS/nvic_table.c \ - $(PERIPH_SRC)/SYS/pins_me10.c \ - $(PERIPH_SRC)/SYS/sys_me10.c \ - $(PERIPH_SRC)/FLC/flc_common.c \ - $(PERIPH_SRC)/FLC/flc_me10.c \ - $(PERIPH_SRC)/FLC/flc_reva.c \ - $(PERIPH_SRC)/GPIO/gpio_common.c \ - $(PERIPH_SRC)/GPIO/gpio_me10.c \ - $(PERIPH_SRC)/GPIO/gpio_reva.c \ - $(PERIPH_SRC)/ICC/icc_me10.c \ - $(PERIPH_SRC)/ICC/icc_reva.c \ - $(PERIPH_SRC)/ICC/icc_common.c \ - $(PERIPH_SRC)/TPU/tpu_me10.c \ - $(PERIPH_SRC)/TPU/tpu_reva.c \ - $(PERIPH_SRC)/UART/uart_common.c \ - $(PERIPH_SRC)/UART/uart_me10.c \ - $(PERIPH_SRC)/UART/uart_reva.c \ - -INC += \ - $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(MAX32_CMSIS)/Include \ - $(TOP)/$(MAX32_CMSIS)/Device/Maxim/MAX32650/Include \ - $(TOP)/$(MAX32_PERIPH)/Include/MAX32650 \ - $(PERIPH_SRC)/SYS \ - $(PERIPH_SRC)/GPIO \ - $(PERIPH_SRC)/ICC \ - $(PERIPH_SRC)/FLC \ - $(PERIPH_SRC)/TPU \ - $(PERIPH_SRC)/UART - - -# The MAX32651EVKIT is pin for pin identical to the MAX32650EVKIT, however the -# MAX32651 has a secure bootloader which requires the image to be signed before -# loading into flash. All MAX32651EVKIT's have the same key for evaluation -# purposes, so create a special flash rule to sign the binary and flash using -# the MSDK. -MCU_PATH = $(TOP)/hw/mcu/analog/max32/ -# Assume no extension for sign utility -SIGN_EXE = sign_app -ifeq ($(OS), Windows_NT) -# Must use .exe extension on Windows, since the binaries -# for Linux may live in the same place. -SIGN_EXE := sign_app.exe -else -UNAME = $(shell uname -s) -ifneq ($(findstring MSYS_NT,$(UNAME)),) -# Must also use .exe extension for MSYS2 -SIGN_EXE := sign_app.exe -endif -endif - -# Rule to sign the build. This will in-place modify the existing .elf file -# an populate the .sig section with the signature value -sign-build: $(BUILD)/$(PROJECT).elf - $(OBJCOPY) $(BUILD)/$(PROJECT).elf -R .sig -O binary $(BUILD)/$(PROJECT).bin - $(MCU_PATH)/Tools/SBT/bin/$(SIGN_EXE) -c MAX32651 \ - key_file="$(MCU_PATH)/Tools/SBT/devices/MAX32651/keys/maximtestcrk.key" \ - ca=$(BUILD)/$(PROJECT).bin sca=$(BUILD)/$(PROJECT).sbin - $(OBJCOPY) $(BUILD)/$(PROJECT).elf --update-section .sig=$(BUILD)/$(PROJECT).sig - -# Optional flash option when running within an installed MSDK to use OpenOCD -# Mainline OpenOCD does not yet have the MAX32's flash algorithm integrated. -# If the MSDK is installed, flash-msdk can be run to utilize the the modified -# openocd with the algorithms -MAXIM_PATH := $(subst \,/,$(MAXIM_PATH)) -flash-msdk: $(BUILD)/$(PROJECT).elf - $(MAXIM_PATH)/Tools/OpenOCD/openocd -s $(MAXIM_PATH)/Tools/OpenOCD/scripts \ - -f interface/cmsis-dap.cfg -f target/max32650.cfg \ - -c "program $(BUILD)/$(PROJECT).elf verify; init; reset; exit" diff --git a/hw/bsp/max32666/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/max32666/FreeRTOSConfig/FreeRTOSConfig.h deleted file mode 100644 index e5a76af85..000000000 --- a/hw/bsp/max32666/FreeRTOSConfig/FreeRTOSConfig.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * FreeRTOS Kernel V10.0.0 - * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. If you wish to use our Amazon - * FreeRTOS name, please do so in a fair use way that does not cause confusion. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html. - *----------------------------------------------------------*/ - -// skip if included from IAR assembler -#ifndef __IASMARM__ - #include "mxc_device.h" -#endif - -/* Cortex M23/M33 port configuration. */ -#define configENABLE_MPU 0 -#define configENABLE_FPU 1 -#define configENABLE_TRUSTZONE 0 -#define configMINIMAL_SECURE_STACK_SIZE (1024) - -#define configUSE_PREEMPTION 1 -#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 -#define configCPU_CLOCK_HZ SystemCoreClock -#define configTICK_RATE_HZ ( 1000 ) -#define configMAX_PRIORITIES ( 5 ) -#define configMINIMAL_STACK_SIZE ( 128 ) -#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) -#define configMAX_TASK_NAME_LEN 16 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_MUTEXES 1 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configQUEUE_REGISTRY_SIZE 4 -#define configUSE_QUEUE_SETS 0 -#define configUSE_TIME_SLICING 0 -#define configUSE_NEWLIB_REENTRANT 0 -#define configENABLE_BACKWARD_COMPATIBILITY 1 -#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 - -#define configSUPPORT_STATIC_ALLOCATION 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 0 - -/* Hook function related definitions. */ -#define configUSE_IDLE_HOOK 0 -#define configUSE_TICK_HOOK 0 -#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning -#define configCHECK_FOR_STACK_OVERFLOW 2 -#define configCHECK_HANDLER_INSTALLATION 0 - -/* Run time and task stats gathering related definitions. */ -#define configGENERATE_RUN_TIME_STATS 0 -#define configRECORD_STACK_HIGH_ADDRESS 1 -#define configUSE_TRACE_FACILITY 1 // legacy trace -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES 2 - -/* Software timer related definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) -#define configTIMER_QUEUE_LENGTH 32 -#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE - -/* Optional functions - most linkers will remove unused functions anyway. */ -#define INCLUDE_vTaskPrioritySet 0 -#define INCLUDE_uxTaskPriorityGet 0 -#define INCLUDE_vTaskDelete 0 -#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY -#define INCLUDE_xResumeFromISR 0 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 0 -#define INCLUDE_xTaskGetCurrentTaskHandle 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 0 -#define INCLUDE_xTaskGetIdleTaskHandle 0 -#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 -#define INCLUDE_pcTaskGetTaskName 0 -#define INCLUDE_eTaskGetState 0 -#define INCLUDE_xEventGroupSetBitFromISR 0 -#define INCLUDE_xTimerPendFunctionCall 0 - -/* FreeRTOS hooks to NVIC vectors */ -#define xPortPendSVHandler PendSV_Handler -#define xPortSysTickHandler SysTick_Handler -#define vPortSVCHandler SVC_Handler - -//--------------------------------------------------------------------+ -// Interrupt nesting behavior configuration. -//--------------------------------------------------------------------+ - -// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header -#define configPRIO_BITS __NVIC_PRIO_BITS - -/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<-jlink` target for CMake. - -Both the Evaluation Kit and Feather boards are shipped with a CMSIS-DAP -compatible debug probe. However, at the time of writing, the necessary flashing -algorithms for OpenOCD have not yet been incorporated into the OpenOCD master -branch. To utilize the provided debug probes, please install the bundled MSDK -package which includes the appropriate OpenOCD modifications. To leverage this -OpenOCD instance, run the `flash-msdk` Makefile rule, or `-msdk` CMake -target. diff --git a/hw/bsp/max32666/boards/max32666evkit/board.cmake b/hw/bsp/max32666/boards/max32666evkit/board.cmake deleted file mode 100644 index 9dc6962eb..000000000 --- a/hw/bsp/max32666/boards/max32666evkit/board.cmake +++ /dev/null @@ -1 +0,0 @@ -# Nothing to be done at the board level diff --git a/hw/bsp/max32666/boards/max32666evkit/board.mk b/hw/bsp/max32666/boards/max32666evkit/board.mk deleted file mode 100644 index a813a5327..000000000 --- a/hw/bsp/max32666/boards/max32666evkit/board.mk +++ /dev/null @@ -1 +0,0 @@ -# No specific build requirements for the board. diff --git a/hw/bsp/max32666/boards/max32666fthr/board.cmake b/hw/bsp/max32666/boards/max32666fthr/board.cmake deleted file mode 100644 index 9dc6962eb..000000000 --- a/hw/bsp/max32666/boards/max32666fthr/board.cmake +++ /dev/null @@ -1 +0,0 @@ -# Nothing to be done at the board level diff --git a/hw/bsp/max32666/boards/max32666fthr/board.mk b/hw/bsp/max32666/boards/max32666fthr/board.mk deleted file mode 100644 index a813a5327..000000000 --- a/hw/bsp/max32666/boards/max32666fthr/board.mk +++ /dev/null @@ -1 +0,0 @@ -# No specific build requirements for the board. diff --git a/hw/bsp/max32666/family.cmake b/hw/bsp/max32666/family.cmake deleted file mode 100644 index 49798729a..000000000 --- a/hw/bsp/max32666/family.cmake +++ /dev/null @@ -1,147 +0,0 @@ -include_guard() - -set(MAX32_PERIPH ${TOP}/hw/mcu/analog/max32/Libraries/PeriphDrivers) -set(MAX32_CMSIS ${TOP}/hw/mcu/analog/max32/Libraries/CMSIS) -set(CMSIS_5 ${TOP}/lib/CMSIS_5) - -# include board specific -include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) - -# Get the linker file from current location (family) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/max32666.ld) -set(LD_FILE_Clang ${LD_FILE_GNU}) - -# toolchain set up -set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") -set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) -set(JLINK_DEVICE max32666) -set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -f target/max32665.cfg") - -set(FAMILY_MCUS MAX32666 CACHE INTERNAL "") - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - TARGET=MAX32665 - TARGET_REV=0x4131 - MXC_ASSERT_ENABLE - MAX32665 - IAR_PRAGMAS=0 - CFG_TUSB_MCU=OPT_MCU_MAX32666 - BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - ) -endfunction() - -#------------------------------------ -# BOARD_TARGET -#------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${MAX32_CMSIS}/Device/Maxim/MAX32665/Source/GCC/startup_max32665.S) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - - set(PERIPH_SRC ${MAX32_PERIPH}/Source) - add_library(${BOARD_TARGET} STATIC - ${MAX32_CMSIS}/Device/Maxim/MAX32665/Source/heap.c - ${MAX32_CMSIS}/Device/Maxim/MAX32665/Source/system_max32665.c - ${PERIPH_SRC}/SYS/mxc_assert.c - ${PERIPH_SRC}/SYS/mxc_delay.c - ${PERIPH_SRC}/SYS/mxc_lock.c - ${PERIPH_SRC}/SYS/nvic_table.c - ${PERIPH_SRC}/SYS/pins_me14.c - ${PERIPH_SRC}/SYS/sys_me14.c - ${PERIPH_SRC}/TPU/tpu_me14.c - ${PERIPH_SRC}/TPU/tpu_reva.c - ${PERIPH_SRC}/FLC/flc_common.c - ${PERIPH_SRC}/FLC/flc_me14.c - ${PERIPH_SRC}/FLC/flc_reva.c - ${PERIPH_SRC}/GPIO/gpio_common.c - ${PERIPH_SRC}/GPIO/gpio_me14.c - ${PERIPH_SRC}/GPIO/gpio_reva.c - ${PERIPH_SRC}/ICC/icc_me14.c - ${PERIPH_SRC}/ICC/icc_reva.c - ${PERIPH_SRC}/UART/uart_common.c - ${PERIPH_SRC}/UART/uart_me14.c - ${PERIPH_SRC}/UART/uart_reva.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${MAX32_CMSIS}/Include - ${MAX32_CMSIS}/Device/Maxim/MAX32665/Include - ${MAX32_PERIPH}/Include/MAX32665 - ${PERIPH_SRC}/SYS - ${PERIPH_SRC}/GPIO - ${PERIPH_SRC}/TPU - ${PERIPH_SRC}/ICC - ${PERIPH_SRC}/FLC - ${PERIPH_SRC}/UART - ) - - target_compile_options(${BOARD_TARGET} PRIVATE - -Wno-error=strict-prototypes - ) - update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - endif () -endfunction() - - -#------------------------------------ -# Functions -#------------------------------------ -function(family_configure_example TARGET RTOS) - family_configure_common(${TARGET} ${RTOS}) - - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h - target_sources(${TARGET} PUBLIC - # BSP - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ) - target_include_directories(${TARGET} PUBLIC - # family, hw, board - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} - ) - - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_MAX32666) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/mentor/musb/dcd_musb.c - ) - target_compile_options(${TARGET} PRIVATE - -Wno-error=strict-prototypes - ) - - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - target_compile_options(${TARGET} PRIVATE - -Wno-error=strict-prototypes - ) - - - - # Flashing - family_add_bin_hex(${TARGET}) - family_flash_jlink(${TARGET}) - family_flash_openocd_adi(${TARGET}) -endfunction() diff --git a/hw/bsp/max32666/family.mk b/hw/bsp/max32666/family.mk deleted file mode 100644 index b4f7d1e57..000000000 --- a/hw/bsp/max32666/family.mk +++ /dev/null @@ -1,93 +0,0 @@ -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/analog/max32 - -# Important locations in the hw support for MCU -MAX32_CMSIS = hw/mcu/analog/max32/Libraries/CMSIS -MAX32_PERIPH = hw/mcu/analog/max32/Libraries/PeriphDrivers - -# Add any board specific make rules -include $(TOP)/$(BOARD_PATH)/board.mk - -CPU_CORE ?= cortex-m4 -PORT ?= 0 - -# GCC -SRC_S_GCC += $(MAX32_CMSIS)/Device/Maxim/MAX32665/Source/GCC/startup_max32665.S -LD_FILE = $(FAMILY_PATH)/max32666.ld - -# -------------- -# Compiler Flags -# -------------- -# Flags for the MAX32665/6 SDK -CFLAGS += -DTARGET=MAX32665 \ - -DTARGET_REV=0x4131 \ - -DMXC_ASSERT_ENABLE \ - -DMAX32665 \ - -DIAR_PRAGMAS=0 - -# Flags for TUSB features -CFLAGS += \ - -DCFG_TUSB_MCU=OPT_MCU_MAX32666 \ - -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - -# mcu driver cause following warnings -CFLAGS += -Wno-error=strict-prototypes \ - -Wno-error=unused-parameter \ - -Wno-error=cast-align \ - -Wno-error=cast-qual -LDFLAGS_GCC += -nostartfiles --specs=nosys.specs --specs=nano.specs - -# For flash-jlink target -JLINK_DEVICE = max32666 - -# flash target using Jlink by default -flash: flash-jlink - -# Optional flash option when running within an installed MSDK to use OpenOCD -# Mainline OpenOCD does not yet have the MAX32's flash algorithm integrated. -# If the MSDK is installed, flash-msdk can be run to utilize the the modified -# openocd with the algorithms -MAXIM_PATH := $(subst \,/,$(MAXIM_PATH)) -flash-msdk: $(BUILD)/$(PROJECT).elf - $(MAXIM_PATH)/Tools/OpenOCD/openocd -s $(MAXIM_PATH)/Tools/OpenOCD/scripts \ - -f interface/cmsis-dap.cfg -f target/max32665.cfg \ - -c "program $(BUILD)/$(PROJECT).elf verify; init; reset; exit" - -# ----------------- -# Sources & Include -# ----------------- -PERIPH_SRC = $(TOP)/$(MAX32_PERIPH)/Source -SRC_C += \ - src/portable/mentor/musb/dcd_musb.c \ - $(MAX32_CMSIS)/Device/Maxim/MAX32665/Source/heap.c \ - $(MAX32_CMSIS)/Device/Maxim/MAX32665/Source/system_max32665.c \ - $(PERIPH_SRC)/SYS/mxc_assert.c \ - $(PERIPH_SRC)/SYS/mxc_delay.c \ - $(PERIPH_SRC)/SYS/mxc_lock.c \ - $(PERIPH_SRC)/SYS/nvic_table.c \ - $(PERIPH_SRC)/SYS/pins_me14.c \ - $(PERIPH_SRC)/SYS/sys_me14.c \ - $(PERIPH_SRC)/FLC/flc_common.c \ - $(PERIPH_SRC)/FLC/flc_me14.c \ - $(PERIPH_SRC)/FLC/flc_reva.c \ - $(PERIPH_SRC)/GPIO/gpio_common.c \ - $(PERIPH_SRC)/GPIO/gpio_me14.c \ - $(PERIPH_SRC)/GPIO/gpio_reva.c \ - $(PERIPH_SRC)/ICC/icc_me14.c \ - $(PERIPH_SRC)/ICC/icc_reva.c \ - $(PERIPH_SRC)/TPU/tpu_me14.c \ - $(PERIPH_SRC)/TPU/tpu_reva.c \ - $(PERIPH_SRC)/UART/uart_common.c \ - $(PERIPH_SRC)/UART/uart_me14.c \ - $(PERIPH_SRC)/UART/uart_reva.c \ - -INC += \ - $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(MAX32_CMSIS)/Include \ - $(TOP)/$(MAX32_CMSIS)/Device/Maxim/MAX32665/Include \ - $(TOP)/$(MAX32_PERIPH)/Include/MAX32665 \ - $(PERIPH_SRC)/SYS \ - $(PERIPH_SRC)/GPIO \ - $(PERIPH_SRC)/ICC \ - $(PERIPH_SRC)/FLC \ - $(PERIPH_SRC)/TPU \ - $(PERIPH_SRC)/UART diff --git a/hw/bsp/max32690/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/max32690/FreeRTOSConfig/FreeRTOSConfig.h deleted file mode 100644 index e5a76af85..000000000 --- a/hw/bsp/max32690/FreeRTOSConfig/FreeRTOSConfig.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * FreeRTOS Kernel V10.0.0 - * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. If you wish to use our Amazon - * FreeRTOS name, please do so in a fair use way that does not cause confusion. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html. - *----------------------------------------------------------*/ - -// skip if included from IAR assembler -#ifndef __IASMARM__ - #include "mxc_device.h" -#endif - -/* Cortex M23/M33 port configuration. */ -#define configENABLE_MPU 0 -#define configENABLE_FPU 1 -#define configENABLE_TRUSTZONE 0 -#define configMINIMAL_SECURE_STACK_SIZE (1024) - -#define configUSE_PREEMPTION 1 -#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 -#define configCPU_CLOCK_HZ SystemCoreClock -#define configTICK_RATE_HZ ( 1000 ) -#define configMAX_PRIORITIES ( 5 ) -#define configMINIMAL_STACK_SIZE ( 128 ) -#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) -#define configMAX_TASK_NAME_LEN 16 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_MUTEXES 1 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configQUEUE_REGISTRY_SIZE 4 -#define configUSE_QUEUE_SETS 0 -#define configUSE_TIME_SLICING 0 -#define configUSE_NEWLIB_REENTRANT 0 -#define configENABLE_BACKWARD_COMPATIBILITY 1 -#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 - -#define configSUPPORT_STATIC_ALLOCATION 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 0 - -/* Hook function related definitions. */ -#define configUSE_IDLE_HOOK 0 -#define configUSE_TICK_HOOK 0 -#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning -#define configCHECK_FOR_STACK_OVERFLOW 2 -#define configCHECK_HANDLER_INSTALLATION 0 - -/* Run time and task stats gathering related definitions. */ -#define configGENERATE_RUN_TIME_STATS 0 -#define configRECORD_STACK_HIGH_ADDRESS 1 -#define configUSE_TRACE_FACILITY 1 // legacy trace -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES 2 - -/* Software timer related definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) -#define configTIMER_QUEUE_LENGTH 32 -#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE - -/* Optional functions - most linkers will remove unused functions anyway. */ -#define INCLUDE_vTaskPrioritySet 0 -#define INCLUDE_uxTaskPriorityGet 0 -#define INCLUDE_vTaskDelete 0 -#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY -#define INCLUDE_xResumeFromISR 0 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 0 -#define INCLUDE_xTaskGetCurrentTaskHandle 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 0 -#define INCLUDE_xTaskGetIdleTaskHandle 0 -#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 -#define INCLUDE_pcTaskGetTaskName 0 -#define INCLUDE_eTaskGetState 0 -#define INCLUDE_xEventGroupSetBitFromISR 0 -#define INCLUDE_xTimerPendFunctionCall 0 - -/* FreeRTOS hooks to NVIC vectors */ -#define xPortPendSVHandler PendSV_Handler -#define xPortSysTickHandler SysTick_Handler -#define vPortSVCHandler SVC_Handler - -//--------------------------------------------------------------------+ -// Interrupt nesting behavior configuration. -//--------------------------------------------------------------------+ - -// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header -#define configPRIO_BITS __NVIC_PRIO_BITS - -/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<-jlink` target for CMake. - -Both the Evaluation Kit and APARD boards are shipped with a CMSIS-DAP -compatible debug probe. However, at the time of writing, the necessary flashing -algorithms for OpenOCD have not yet been incorporated into the OpenOCD master -branch. To utilize the provided debug probes, please install the bundled MSDK -package which includes the appropriate OpenOCD modifications. To leverage this -OpenOCD instance, run the `flash-msdk` Makefile rule, or `-msdk` CMake -target. diff --git a/hw/bsp/max32690/boards/apard32690/board.cmake b/hw/bsp/max32690/boards/apard32690/board.cmake deleted file mode 100644 index 9dc6962eb..000000000 --- a/hw/bsp/max32690/boards/apard32690/board.cmake +++ /dev/null @@ -1 +0,0 @@ -# Nothing to be done at the board level diff --git a/hw/bsp/max32690/boards/apard32690/board.mk b/hw/bsp/max32690/boards/apard32690/board.mk deleted file mode 100644 index a813a5327..000000000 --- a/hw/bsp/max32690/boards/apard32690/board.mk +++ /dev/null @@ -1 +0,0 @@ -# No specific build requirements for the board. diff --git a/hw/bsp/max32690/boards/max32690evkit/board.cmake b/hw/bsp/max32690/boards/max32690evkit/board.cmake deleted file mode 100644 index 9dc6962eb..000000000 --- a/hw/bsp/max32690/boards/max32690evkit/board.cmake +++ /dev/null @@ -1 +0,0 @@ -# Nothing to be done at the board level diff --git a/hw/bsp/max32690/boards/max32690evkit/board.mk b/hw/bsp/max32690/boards/max32690evkit/board.mk deleted file mode 100644 index a813a5327..000000000 --- a/hw/bsp/max32690/boards/max32690evkit/board.mk +++ /dev/null @@ -1 +0,0 @@ -# No specific build requirements for the board. diff --git a/hw/bsp/max32690/family.c b/hw/bsp/max32690/family.c deleted file mode 100644 index 7ba5fbef3..000000000 --- a/hw/bsp/max32690/family.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 Brent Kowal (Analog Devices, Inc) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/* metadata: - manufacturer: Analog Devices -*/ - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-prototypes" // _mxc_crit_get_state() -#endif - -#include "gpio.h" -#include "mxc_sys.h" -#include "mcr_regs.h" -#include "mxc_device.h" -#include "uart.h" - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - -#include "board.h" -#include "bsp/board_api.h" - - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USB_IRQHandler(void) { - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ -mxc_uart_regs_t *ConsoleUart = MXC_UART_GET_UART(UART_NUM); - -void board_init(void) { -#if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer - SysTick_Config(SystemCoreClock / 1000); -#elif CFG_TUSB_OS == OPT_OS_FREERTOS - // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); -#endif - mxc_gpio_cfg_t gpioConfig; - - // LED - gpioConfig.drvstr = MXC_GPIO_DRVSTR_0; - gpioConfig.func = MXC_GPIO_FUNC_OUT; - gpioConfig.mask = LED_PIN; - gpioConfig.pad = MXC_GPIO_PAD_NONE; - gpioConfig.port = LED_PORT; - gpioConfig.vssel = LED_VDDIO; - MXC_GPIO_Config(&gpioConfig); - board_led_write(false); - - // Button - gpioConfig.drvstr = MXC_GPIO_DRVSTR_0; - gpioConfig.func = MXC_GPIO_FUNC_IN; - gpioConfig.mask = BUTTON_PIN; - gpioConfig.pad = BUTTON_PULL; - gpioConfig.port = BUTTON_PORT; - gpioConfig.vssel = MXC_GPIO_VSSEL_VDDIO; - MXC_GPIO_Config(&gpioConfig); - - // UART - MXC_UART_Init(ConsoleUart, CFG_BOARD_UART_BAUDRATE, MXC_UART_IBRO_CLK); - - //USB - MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IPO); - MXC_MCR->ldoctrl |= MXC_F_MCR_LDOCTRL_0P9EN; - MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); - MXC_SYS_Reset_Periph(MXC_SYS_RESET0_USB); -} - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) { -#if LED_STATE_ON - state = !state; -#endif - if (state) { - MXC_GPIO_OutClr(LED_PORT, LED_PIN); - } else { - MXC_GPIO_OutSet(LED_PORT, LED_PIN); - } -} - -uint32_t board_button_read(void) { - uint32_t state = MXC_GPIO_InGet(BUTTON_PORT, BUTTON_PIN) ? 1 : 0; - return BUTTON_STATE_ACTIVE == state; -} - -size_t board_get_unique_id(uint8_t id[], size_t max_len) { - uint8_t hw_id[MXC_SYS_USN_CHECKSUM_LEN];//USN Buffer - /* All other 2nd parameter is optional checksum buffer */ - MXC_SYS_GetUSN(hw_id, NULL); - - size_t act_len = TU_MIN(max_len, MXC_SYS_USN_LEN); - memcpy(id, hw_id, act_len); - return act_len; -} - -int board_uart_read(uint8_t *buf, int len) { - int uart_val; - int act_len = 0; - - while (act_len < len) { - if ((uart_val = MXC_UART_ReadCharacterRaw(ConsoleUart)) == E_UNDERFLOW) { - break; - } else { - *buf++ = (uint8_t) uart_val; - act_len++; - } - } - return act_len; -} - -int board_uart_write(void const *buf, int len) { - int act_len = 0; - const uint8_t *ch_ptr = (const uint8_t *) buf; - while (act_len < len) { - MXC_UART_WriteCharacter(ConsoleUart, *ch_ptr++); - act_len++; - } - return len; -} - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; - -void SysTick_Handler(void) { - system_ticks++; -} - -uint32_t board_millis(void) { - return system_ticks; -} -#endif - -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) { -} diff --git a/hw/bsp/max32690/family.cmake b/hw/bsp/max32690/family.cmake deleted file mode 100644 index 0d544d9e6..000000000 --- a/hw/bsp/max32690/family.cmake +++ /dev/null @@ -1,152 +0,0 @@ -include_guard() - -set(MAX32_PERIPH ${TOP}/hw/mcu/analog/max32/Libraries/PeriphDrivers) -set(MAX32_CMSIS ${TOP}/hw/mcu/analog/max32/Libraries/CMSIS) -set(CMSIS_5 ${TOP}/lib/CMSIS_5) - -# include board specific -include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) - -# Get the linker file from current location (family) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/max32690.ld) -set(LD_FILE_Clang ${LD_FILE_GNU}) - -# toolchain set up -set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") -set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) -set(JLINK_DEVICE max32690) -set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -f target/max32690.cfg") - -set(FAMILY_MCUS MAX32690 CACHE INTERNAL "") - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - TARGET=MAX32690 - TARGET_REV=0x4131 - MXC_ASSERT_ENABLE - MAX32690 - FLASH_ORIGIN=0x10000000 - FLASH_SIZE=0x340000 - SRAM_ORIGIN=0x20000000 - SRAM_SIZE=0x100000 - IAR_PRAGMAS=0 - CFG_TUSB_MCU=OPT_MCU_MAX32690 - BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - ) -endfunction() - -#------------------------------------ -# BOARD_TARGET -#------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${MAX32_CMSIS}/Device/Maxim/MAX32690/Source/GCC/startup_max32690.S) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - - set(PERIPH_SRC ${MAX32_PERIPH}/Source) - add_library(${BOARD_TARGET} STATIC - ${MAX32_CMSIS}/Device/Maxim/MAX32690/Source/heap.c - ${MAX32_CMSIS}/Device/Maxim/MAX32690/Source/system_max32690.c - ${PERIPH_SRC}/SYS/mxc_assert.c - ${PERIPH_SRC}/SYS/mxc_delay.c - ${PERIPH_SRC}/SYS/mxc_lock.c - ${PERIPH_SRC}/SYS/nvic_table.c - ${PERIPH_SRC}/SYS/pins_me18.c - ${PERIPH_SRC}/SYS/sys_me18.c - ${PERIPH_SRC}/CTB/ctb_me18.c - ${PERIPH_SRC}/CTB/ctb_reva.c - ${PERIPH_SRC}/CTB/ctb_common.c - ${PERIPH_SRC}/FLC/flc_common.c - ${PERIPH_SRC}/FLC/flc_me18.c - ${PERIPH_SRC}/FLC/flc_reva.c - ${PERIPH_SRC}/GPIO/gpio_common.c - ${PERIPH_SRC}/GPIO/gpio_me18.c - ${PERIPH_SRC}/GPIO/gpio_reva.c - ${PERIPH_SRC}/ICC/icc_me18.c - ${PERIPH_SRC}/ICC/icc_reva.c - ${PERIPH_SRC}/UART/uart_common.c - ${PERIPH_SRC}/UART/uart_me18.c - ${PERIPH_SRC}/UART/uart_revb.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${MAX32_CMSIS}/Include - ${MAX32_CMSIS}/Device/Maxim/MAX32690/Include - ${MAX32_PERIPH}/Include/MAX32690 - ${PERIPH_SRC}/SYS - ${PERIPH_SRC}/GPIO - ${PERIPH_SRC}/CTB - ${PERIPH_SRC}/ICC - ${PERIPH_SRC}/FLC - ${PERIPH_SRC}/UART - ) - - target_compile_options(${BOARD_TARGET} PRIVATE - -Wno-error=strict-prototypes - ) - update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - endif () -endfunction() - - -#------------------------------------ -# Functions -#------------------------------------ -function(family_configure_example TARGET RTOS) - family_configure_common(${TARGET} ${RTOS}) - - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h - target_sources(${TARGET} PUBLIC - # BSP - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ) - target_include_directories(${TARGET} PUBLIC - # family, hw, board - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} - ) - - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_MAX32690) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/mentor/musb/dcd_musb.c - ) - target_compile_options(${TARGET} PRIVATE - -Wno-error=strict-prototypes - ) - - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - target_compile_options(${TARGET} PRIVATE - -Wno-error=strict-prototypes - ) - - - - # Flashing - family_add_bin_hex(${TARGET}) - family_flash_jlink(${TARGET}) - family_flash_openocd_adi(${TARGET}) -endfunction() diff --git a/hw/bsp/max32690/family.mk b/hw/bsp/max32690/family.mk deleted file mode 100644 index d4df8ef2f..000000000 --- a/hw/bsp/max32690/family.mk +++ /dev/null @@ -1,101 +0,0 @@ -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/analog/max32 - -# Important locations in the hw support for MCU -MAX32_CMSIS = hw/mcu/analog/max32/Libraries/CMSIS -MAX32_PERIPH = hw/mcu/analog/max32/Libraries/PeriphDrivers - -# Add any board specific make rules -include $(TOP)/$(BOARD_PATH)/board.mk - -CPU_CORE ?= cortex-m4 -PORT ?= 0 - -# GCC -SRC_S_GCC += $(MAX32_CMSIS)/Device/Maxim/MAX32690/Source/GCC/startup_max32690.S -LD_FILE = $(FAMILY_PATH)/max32690.ld - -# -------------- -# Compiler Flags -# -------------- -# Flags for the MAX32690 SDK -CFLAGS += -DTARGET=MAX32690 \ - -DTARGET_REV=0x4131 \ - -DMXC_ASSERT_ENABLE \ - -DMAX32690 \ - -DFLASH_ORIGIN=0x10000000 \ - -DFLASH_SIZE=0x340000 \ - -DSRAM_ORIGIN=0x20000000 \ - -DSRAM_SIZE=0x100000 \ - -DIAR_PRAGMAS=0 - -# Flags for TUSB features -CFLAGS += \ - -DCFG_TUSB_MCU=OPT_MCU_MAX32690 \ - -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - -# mcu driver cause following warnings -CFLAGS += -Wno-error=unused-parameter \ - -Wno-error=strict-prototypes \ - -Wno-error=old-style-declaration \ - -Wno-error=sign-compare \ - -Wno-error=cast-qual \ - -Wno-lto-type-mismatch - -LDFLAGS_GCC += -nostartfiles --specs=nosys.specs --specs=nano.specs - -# For flash-jlink target -JLINK_DEVICE = max32690 - -# flash target using Jlink by default -flash: flash-jlink - -# Optional flash option when running within an installed MSDK to use OpenOCD -# Mainline OpenOCD does not yet have the MAX32's flash algorithm integrated. -# If the MSDK is installed, flash-msdk can be run to utilize the the modified -# openocd with the algorithms -MAXIM_PATH := $(subst \,/,$(MAXIM_PATH)) -flash-msdk: $(BUILD)/$(PROJECT).elf - $(MAXIM_PATH)/Tools/OpenOCD/openocd -s $(MAXIM_PATH)/Tools/OpenOCD/scripts \ - -f interface/cmsis-dap.cfg -f target/max32690.cfg \ - -c "program $(BUILD)/$(PROJECT).elf verify; init; reset; exit" - -# ----------------- -# Sources & Include -# ----------------- -PERIPH_SRC = $(TOP)/$(MAX32_PERIPH)/Source -SRC_C += \ - src/portable/mentor/musb/dcd_musb.c \ - $(MAX32_CMSIS)/Device/Maxim/MAX32690/Source/heap.c \ - $(MAX32_CMSIS)/Device/Maxim/MAX32690/Source/system_max32690.c \ - $(PERIPH_SRC)/SYS/mxc_assert.c \ - $(PERIPH_SRC)/SYS/mxc_delay.c \ - $(PERIPH_SRC)/SYS/mxc_lock.c \ - $(PERIPH_SRC)/SYS/nvic_table.c \ - $(PERIPH_SRC)/SYS/pins_me18.c \ - $(PERIPH_SRC)/SYS/sys_me18.c \ - $(PERIPH_SRC)/CTB/ctb_me18.c \ - $(PERIPH_SRC)/CTB/ctb_reva.c \ - $(PERIPH_SRC)/CTB/ctb_common.c \ - $(PERIPH_SRC)/FLC/flc_common.c \ - $(PERIPH_SRC)/FLC/flc_me18.c \ - $(PERIPH_SRC)/FLC/flc_reva.c \ - $(PERIPH_SRC)/GPIO/gpio_common.c \ - $(PERIPH_SRC)/GPIO/gpio_me18.c \ - $(PERIPH_SRC)/GPIO/gpio_reva.c \ - $(PERIPH_SRC)/ICC/icc_me18.c \ - $(PERIPH_SRC)/ICC/icc_reva.c \ - $(PERIPH_SRC)/UART/uart_common.c \ - $(PERIPH_SRC)/UART/uart_me18.c \ - $(PERIPH_SRC)/UART/uart_revb.c \ - -INC += \ - $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(MAX32_CMSIS)/Include \ - $(TOP)/$(MAX32_CMSIS)/Device/Maxim/MAX32690/Include \ - $(TOP)/$(MAX32_PERIPH)/Include/MAX32690 \ - $(PERIPH_SRC)/SYS \ - $(PERIPH_SRC)/GPIO \ - $(PERIPH_SRC)/CTB \ - $(PERIPH_SRC)/ICC \ - $(PERIPH_SRC)/FLC \ - $(PERIPH_SRC)/UART diff --git a/hw/bsp/max78002/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/max78002/FreeRTOSConfig/FreeRTOSConfig.h deleted file mode 100644 index e5a76af85..000000000 --- a/hw/bsp/max78002/FreeRTOSConfig/FreeRTOSConfig.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * FreeRTOS Kernel V10.0.0 - * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. If you wish to use our Amazon - * FreeRTOS name, please do so in a fair use way that does not cause confusion. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html. - *----------------------------------------------------------*/ - -// skip if included from IAR assembler -#ifndef __IASMARM__ - #include "mxc_device.h" -#endif - -/* Cortex M23/M33 port configuration. */ -#define configENABLE_MPU 0 -#define configENABLE_FPU 1 -#define configENABLE_TRUSTZONE 0 -#define configMINIMAL_SECURE_STACK_SIZE (1024) - -#define configUSE_PREEMPTION 1 -#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 -#define configCPU_CLOCK_HZ SystemCoreClock -#define configTICK_RATE_HZ ( 1000 ) -#define configMAX_PRIORITIES ( 5 ) -#define configMINIMAL_STACK_SIZE ( 128 ) -#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) -#define configMAX_TASK_NAME_LEN 16 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_MUTEXES 1 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configQUEUE_REGISTRY_SIZE 4 -#define configUSE_QUEUE_SETS 0 -#define configUSE_TIME_SLICING 0 -#define configUSE_NEWLIB_REENTRANT 0 -#define configENABLE_BACKWARD_COMPATIBILITY 1 -#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 - -#define configSUPPORT_STATIC_ALLOCATION 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 0 - -/* Hook function related definitions. */ -#define configUSE_IDLE_HOOK 0 -#define configUSE_TICK_HOOK 0 -#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning -#define configCHECK_FOR_STACK_OVERFLOW 2 -#define configCHECK_HANDLER_INSTALLATION 0 - -/* Run time and task stats gathering related definitions. */ -#define configGENERATE_RUN_TIME_STATS 0 -#define configRECORD_STACK_HIGH_ADDRESS 1 -#define configUSE_TRACE_FACILITY 1 // legacy trace -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES 2 - -/* Software timer related definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) -#define configTIMER_QUEUE_LENGTH 32 -#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE - -/* Optional functions - most linkers will remove unused functions anyway. */ -#define INCLUDE_vTaskPrioritySet 0 -#define INCLUDE_uxTaskPriorityGet 0 -#define INCLUDE_vTaskDelete 0 -#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY -#define INCLUDE_xResumeFromISR 0 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 0 -#define INCLUDE_xTaskGetCurrentTaskHandle 1 -#define INCLUDE_uxTaskGetStackHighWaterMark 0 -#define INCLUDE_xTaskGetIdleTaskHandle 0 -#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 -#define INCLUDE_pcTaskGetTaskName 0 -#define INCLUDE_eTaskGetState 0 -#define INCLUDE_xEventGroupSetBitFromISR 0 -#define INCLUDE_xTimerPendFunctionCall 0 - -/* FreeRTOS hooks to NVIC vectors */ -#define xPortPendSVHandler PendSV_Handler -#define xPortSysTickHandler SysTick_Handler -#define vPortSVCHandler SVC_Handler - -//--------------------------------------------------------------------+ -// Interrupt nesting behavior configuration. -//--------------------------------------------------------------------+ - -// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header -#define configPRIO_BITS __NVIC_PRIO_BITS - -/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<-jlink` target for CMake. - -The Evaluation Kit is shipped with a CMSIS-DAP compatible debug probe. However, -at the time of writing, the necessary flashing algorithms for OpenOCD have not -yet been incorporated into the OpenOCD master branch. To utilize the provided -debug probes, please install the bundled MSDK package which includes the -appropriate OpenOCD modifications. To leverage this OpenOCD instance, run the -`flash-msdk` Makefile rule, or `-msdk` CMake target. diff --git a/hw/bsp/max78002/boards/max78002evkit/board.cmake b/hw/bsp/max78002/boards/max78002evkit/board.cmake deleted file mode 100644 index 9dc6962eb..000000000 --- a/hw/bsp/max78002/boards/max78002evkit/board.cmake +++ /dev/null @@ -1 +0,0 @@ -# Nothing to be done at the board level diff --git a/hw/bsp/max78002/boards/max78002evkit/board.mk b/hw/bsp/max78002/boards/max78002evkit/board.mk deleted file mode 100644 index a813a5327..000000000 --- a/hw/bsp/max78002/boards/max78002evkit/board.mk +++ /dev/null @@ -1 +0,0 @@ -# No specific build requirements for the board. diff --git a/hw/bsp/max78002/family.c b/hw/bsp/max78002/family.c deleted file mode 100644 index 5c23f40f9..000000000 --- a/hw/bsp/max78002/family.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2024 Brent Kowal (Analog Devices, Inc) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/* metadata: - manufacturer: Analog Devices -*/ - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstrict-prototypes" // _mxc_crit_get_state() -#endif - -#include "gpio.h" -#include "mxc_sys.h" -#include "mcr_regs.h" -#include "mxc_device.h" -#include "uart.h" - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - -#include "board.h" -#include "bsp/board_api.h" - -//--------------------------------------------------------------------+ -// Forward USB interrupt events to TinyUSB IRQ Handler -//--------------------------------------------------------------------+ -void USB_IRQHandler(void) { - tud_int_handler(0); -} - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ -mxc_uart_regs_t *ConsoleUart = MXC_UART_GET_UART(UART_NUM); - -void board_init(void) { -#if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer - SysTick_Config(SystemCoreClock / 1000); -#elif CFG_TUSB_OS == OPT_OS_FREERTOS - // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); -#endif - mxc_gpio_cfg_t gpioConfig; - - // LED - gpioConfig.drvstr = MXC_GPIO_DRVSTR_0; - gpioConfig.func = MXC_GPIO_FUNC_OUT; - gpioConfig.mask = LED_PIN; - gpioConfig.pad = MXC_GPIO_PAD_NONE; - gpioConfig.port = LED_PORT; - gpioConfig.vssel = LED_VDDIO; - MXC_GPIO_Config(&gpioConfig); - board_led_write(false); - - // Button - gpioConfig.drvstr = MXC_GPIO_DRVSTR_0; - gpioConfig.func = MXC_GPIO_FUNC_IN; - gpioConfig.mask = BUTTON_PIN; - gpioConfig.pad = BUTTON_PULL; - gpioConfig.port = BUTTON_PORT; - gpioConfig.vssel = MXC_GPIO_VSSEL_VDDIO; - MXC_GPIO_Config(&gpioConfig); - - // UART - MXC_UART_Init(ConsoleUart, CFG_BOARD_UART_BAUDRATE, MXC_UART_IBRO_CLK); - UART_PORT->vssel |= UART_VDDIO_BITS; //Set necessary bits to 3.3V - - //USB - MXC_MCR->ldoctrl |= MXC_F_MCR_LDOCTRL_0P9EN; - MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); -} - -//--------------------------------------------------------------------+ -// Board porting API -//--------------------------------------------------------------------+ - -void board_led_write(bool state) { -#if LED_STATE_ON - state = !state; -#endif - if (state) { - MXC_GPIO_OutClr(LED_PORT, LED_PIN); - } else { - MXC_GPIO_OutSet(LED_PORT, LED_PIN); - } -} - -uint32_t board_button_read(void) { - uint32_t state = MXC_GPIO_InGet(BUTTON_PORT, BUTTON_PIN) ? 1 : 0; - return BUTTON_STATE_ACTIVE == state; -} - -size_t board_get_unique_id(uint8_t id[], size_t max_len) { - uint8_t hw_id[MXC_SYS_USN_CHECKSUM_LEN];//USN Buffer - /* All other 2nd parameter is optional checksum buffer */ - MXC_SYS_GetUSN(hw_id, NULL); - - size_t act_len = TU_MIN(max_len, MXC_SYS_USN_LEN); - memcpy(id, hw_id, act_len); - return act_len; -} - -int board_uart_read(uint8_t *buf, int len) { - int uart_val; - int act_len = 0; - - while (act_len < len) { - if ((uart_val = MXC_UART_ReadCharacterRaw(ConsoleUart)) == E_UNDERFLOW) { - break; - } else { - *buf++ = (uint8_t) uart_val; - act_len++; - } - } - return act_len; -} - -int board_uart_write(void const *buf, int len) { - int act_len = 0; - const uint8_t *ch_ptr = (const uint8_t *) buf; - while (act_len < len) { - MXC_UART_WriteCharacter(ConsoleUart, *ch_ptr++); - act_len++; - } - return len; -} - -#if CFG_TUSB_OS == OPT_OS_NONE -volatile uint32_t system_ticks = 0; - -void SysTick_Handler(void) { - system_ticks++; -} - -uint32_t board_millis(void) { - return system_ticks; -} -#endif - -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) { -} diff --git a/hw/bsp/max78002/family.cmake b/hw/bsp/max78002/family.cmake deleted file mode 100644 index ce0fcfa08..000000000 --- a/hw/bsp/max78002/family.cmake +++ /dev/null @@ -1,166 +0,0 @@ -include_guard() - -set(MAX32_PERIPH ${TOP}/hw/mcu/analog/max32/Libraries/PeriphDrivers) -set(MAX32_CMSIS ${TOP}/hw/mcu/analog/max32/Libraries/CMSIS) -set(CMSIS_5 ${TOP}/lib/CMSIS_5) - -# include board specific -include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) - -# Get the linker file from current location (family) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/max78002.ld) -set(LD_FILE_Clang ${LD_FILE_GNU}) - -# toolchain set up -set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") -set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) -set(JLINK_DEVICE max78000) - -set(FAMILY_MCUS MAX78002 CACHE INTERNAL "") - -function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - TARGET=MAX78002 - TARGET_REV=0x4131 - MXC_ASSERT_ENABLE - MAX78002 - IAR_PRAGMAS=0 - CFG_TUSB_MCU=OPT_MCU_MAX78002 - BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - ) -endfunction() - -#------------------------------------ -# BOARD_TARGET -#------------------------------------ -# only need to be built ONCE for all examples -function(add_board_target BOARD_TARGET) - if (TARGET ${BOARD_TARGET}) - return() - endif () - - # Startup & Linker script - set(STARTUP_FILE_GNU ${MAX32_CMSIS}/Device/Maxim/MAX78002/Source/GCC/startup_max78002.S) - set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - - set(PERIPH_SRC ${MAX32_PERIPH}/Source) - add_library(${BOARD_TARGET} STATIC - ${MAX32_CMSIS}/Device/Maxim/MAX78002/Source/heap.c - ${MAX32_CMSIS}/Device/Maxim/MAX78002/Source/system_max78002.c - ${PERIPH_SRC}/SYS/mxc_assert.c - ${PERIPH_SRC}/SYS/mxc_delay.c - ${PERIPH_SRC}/SYS/mxc_lock.c - ${PERIPH_SRC}/SYS/nvic_table.c - ${PERIPH_SRC}/SYS/pins_ai87.c - ${PERIPH_SRC}/SYS/sys_ai87.c - ${PERIPH_SRC}/AES/aes_ai87.c - ${PERIPH_SRC}/AES/aes_revb.c - ${PERIPH_SRC}/FLC/flc_common.c - ${PERIPH_SRC}/FLC/flc_ai87.c - ${PERIPH_SRC}/FLC/flc_reva.c - ${PERIPH_SRC}/GPIO/gpio_common.c - ${PERIPH_SRC}/GPIO/gpio_ai87.c - ${PERIPH_SRC}/GPIO/gpio_reva.c - ${PERIPH_SRC}/ICC/icc_ai87.c - ${PERIPH_SRC}/ICC/icc_reva.c - ${PERIPH_SRC}/TRNG/trng_ai87.c - ${PERIPH_SRC}/TRNG/trng_revb.c - ${PERIPH_SRC}/UART/uart_common.c - ${PERIPH_SRC}/UART/uart_ai87.c - ${PERIPH_SRC}/UART/uart_revb.c - ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} - ) - target_include_directories(${BOARD_TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${MAX32_CMSIS}/Include - ${MAX32_CMSIS}/Device/Maxim/MAX78002/Include - ${MAX32_PERIPH}/Include/MAX78002 - ${PERIPH_SRC}/SYS - ${PERIPH_SRC}/GPIO - ${PERIPH_SRC}/AES - ${PERIPH_SRC}/TRNG - ${PERIPH_SRC}/ICC - ${PERIPH_SRC}/FLC - ${PERIPH_SRC}/UART - ) - - target_compile_options(${BOARD_TARGET} PRIVATE - -Wno-error=strict-prototypes - -Wno-error=redundant-decls - ) - update_board(${BOARD_TARGET}) - - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_GNU}" - -nostartfiles - --specs=nosys.specs --specs=nano.specs - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_link_options(${BOARD_TARGET} PUBLIC - "LINKER:--script=${LD_FILE_Clang}" - ) - endif () -endfunction() - - -#------------------------------------ -# Functions -#------------------------------------ -function(family_configure_example TARGET RTOS) - family_configure_common(${TARGET} ${RTOS}) - - # Board target - add_board_target(board_${BOARD}) - - #---------- Port Specific ---------- - # These files are built for each example since it depends on example's tusb_config.h - target_sources(${TARGET} PUBLIC - # BSP - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ) - target_include_directories(${TARGET} PUBLIC - # family, hw, board - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} - ) - - target_compile_options(${TARGET} PRIVATE - -Wno-error=strict-prototypes - -Wno-error=redundant-decls - ) - - - # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_MAX78002) - target_sources(${TARGET} PUBLIC - ${TOP}/src/portable/mentor/musb/dcd_musb.c - ) - target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - target_compile_options(${TARGET} PRIVATE - -Wno-error=strict-prototypes - -Wno-error=redundant-decls - ) - - - - # Flashing - family_add_bin_hex(${TARGET}) - family_flash_jlink(${TARGET}) - family_flash_msdk(${TARGET}) -endfunction() - -# Add flash msdk target -function(family_flash_msdk TARGET) - set(MAXIM_PATH "$ENV{MAXIM_PATH}") - - add_custom_target(${TARGET}-msdk - DEPENDS ${TARGET} - COMMAND ${MAXIM_PATH}/Tools/OpenOCD/openocd -s ${MAXIM_PATH}/Tools/OpenOCD/scripts - -f interface/cmsis-dap.cfg -f target/max78002.cfg - -c "program $ verify; init; reset; exit" - VERBATIM - ) -endfunction() diff --git a/hw/bsp/max78002/family.mk b/hw/bsp/max78002/family.mk deleted file mode 100644 index 997816261..000000000 --- a/hw/bsp/max78002/family.mk +++ /dev/null @@ -1,99 +0,0 @@ -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/analog/max32 - -# Important locations in the hw support for MCU -MAX32_CMSIS = hw/mcu/analog/max32/Libraries/CMSIS -MAX32_PERIPH = hw/mcu/analog/max32/Libraries/PeriphDrivers - -# Add any board specific make rules -include $(TOP)/$(BOARD_PATH)/board.mk - -CPU_CORE ?= cortex-m4 -PORT ?= 0 - -# GCC -SRC_S_GCC += $(MAX32_CMSIS)/Device/Maxim/MAX78002/Source/GCC/startup_max78002.S -LD_FILE = $(FAMILY_PATH)/max78002.ld - -# -------------- -# Compiler Flags -# -------------- -# Flags for the MAX78002 SDK -CFLAGS += -DTARGET=MAX78002 \ - -DTARGET_REV=0x4131 \ - -DMXC_ASSERT_ENABLE \ - -DMAX78002 \ - -DIAR_PRAGMAS=0 - -# Flags for TUSB features -CFLAGS += \ - -DCFG_TUSB_MCU=OPT_MCU_MAX78002 \ - -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED - -# mcu driver cause following warnings -CFLAGS += -Wno-error=redundant-decls \ - -Wno-error=strict-prototypes \ - -Wno-error=unused-parameter \ - -Wno-error=enum-conversion \ - -Wno-error=sign-compare \ - -Wno-error=cast-qual - -LDFLAGS_GCC += -nostartfiles --specs=nosys.specs --specs=nano.specs - -# For flash-jlink target -JLINK_DEVICE = max78000 - -# flash target using Jlink by default -flash: flash-jlink - -# Optional flash option when running within an installed MSDK to use OpenOCD -# Mainline OpenOCD does not yet have the MAX32's flash algorithm integrated. -# If the MSDK is installed, flash-msdk can be run to utilize the the modified -# openocd with the algorithms -MAXIM_PATH := $(subst \,/,$(MAXIM_PATH)) -flash-msdk: $(BUILD)/$(PROJECT).elf - $(MAXIM_PATH)/Tools/OpenOCD/openocd -s $(MAXIM_PATH)/Tools/OpenOCD/scripts \ - -f interface/cmsis-dap.cfg -f target/max78002.cfg \ - -c "program $(BUILD)/$(PROJECT).elf verify; init; reset; exit" - -# ----------------- -# Sources & Include -# ----------------- -PERIPH_SRC = $(TOP)/$(MAX32_PERIPH)/Source -SRC_C += \ - src/portable/mentor/musb/dcd_musb.c \ - $(MAX32_CMSIS)/Device/Maxim/MAX78002/Source/heap.c \ - $(MAX32_CMSIS)/Device/Maxim/MAX78002/Source/system_max78002.c \ - $(PERIPH_SRC)/SYS/mxc_assert.c \ - $(PERIPH_SRC)/SYS/mxc_delay.c \ - $(PERIPH_SRC)/SYS/mxc_lock.c \ - $(PERIPH_SRC)/SYS/nvic_table.c \ - $(PERIPH_SRC)/SYS/pins_ai87.c \ - $(PERIPH_SRC)/SYS/sys_ai87.c \ - $(PERIPH_SRC)/AES/aes_ai87.c \ - $(PERIPH_SRC)/AES/aes_revb.c \ - $(PERIPH_SRC)/FLC/flc_common.c \ - $(PERIPH_SRC)/FLC/flc_ai87.c \ - $(PERIPH_SRC)/FLC/flc_reva.c \ - $(PERIPH_SRC)/GPIO/gpio_common.c \ - $(PERIPH_SRC)/GPIO/gpio_ai87.c \ - $(PERIPH_SRC)/GPIO/gpio_reva.c \ - $(PERIPH_SRC)/ICC/icc_ai87.c \ - $(PERIPH_SRC)/ICC/icc_reva.c \ - $(PERIPH_SRC)/TRNG/trng_ai87.c \ - $(PERIPH_SRC)/TRNG/trng_revb.c \ - $(PERIPH_SRC)/UART/uart_common.c \ - $(PERIPH_SRC)/UART/uart_ai87.c \ - $(PERIPH_SRC)/UART/uart_revb.c \ - -INC += \ - $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(MAX32_CMSIS)/Include \ - $(TOP)/$(MAX32_CMSIS)/Device/Maxim/MAX78002/Include \ - $(TOP)/$(MAX32_PERIPH)/Include/MAX78002 \ - $(PERIPH_SRC)/SYS \ - $(PERIPH_SRC)/GPIO \ - $(PERIPH_SRC)/AES \ - $(PERIPH_SRC)/ICC \ - $(PERIPH_SRC)/FLC \ - $(PERIPH_SRC)/TRNG \ - $(PERIPH_SRC)/UART diff --git a/hw/bsp/max32650/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/maxim/FreeRTOSConfig/FreeRTOSConfig.h similarity index 100% rename from hw/bsp/max32650/FreeRTOSConfig/FreeRTOSConfig.h rename to hw/bsp/maxim/FreeRTOSConfig/FreeRTOSConfig.h diff --git a/hw/bsp/maxim/README.md b/hw/bsp/maxim/README.md new file mode 100644 index 000000000..c4b9f0bfc --- /dev/null +++ b/hw/bsp/maxim/README.md @@ -0,0 +1,43 @@ +# Analog Devices MAXIM + +This BSP is for working with the Analog microcontrollers + - [MAX32650](https://www.analog.com/en/products/max32650.html), + - [MAX32651](https://www.analog.com/en/products/max32651.html) + - [MAX32652](https://www.analog.com/en/products/max32652.html) + - [MAX32665](https://www.analog.com/en/products/max32665.html) + - [MAX32666](https://www.analog.com/en/products/max32666.html) + - [MAX32690](https://www.analog.com/en/products/max32690.html) + - [MAX78002](https://www.analog.com/en/products/max78002.html) AI microcontroller. + +The following boards are supported: + * [MAX32650EVKIT](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/max32650-evkit.html) + * [MAX32650FTHR](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/max32650fthr.html) + * [MAX32651EVKIT](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/max32651-evkit.html) (Secure Bootloader) + * [MAX32666EVKIT](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/max32666evkit.html) + * [MAX32666FTHR](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/max32666fthr.html) + * [MAX32690EVKIT](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/max32690evkit.html) + * [AD-APARD32690-SL](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/ad-apard32690-sl.html) + * [MAX78002EVKIT](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/max78002evkit.html) + +This part family leverages the Maxim Microcontrollers SDK (MSDK) for the device +interfaces and hardware abstraction layers. This source code package is fetched +as part of the get-deps script. + +The microcontroller utilizes the standard GNU ARM toolchain. If this toolchain +is not already available on your build machine, it can be installed by using the +bundled MSDK installation. Details on downloading and installing can be found +in the [User's Guide](https://analogdevicesinc.github.io/msdk//USERGUIDE/). + +## Flashing + +The default flashing behavior in this BSP is to utilize JLink. This can be done +by running the `flash` or `flash-jlink` rule for Makefiles, or the +`-jlink` target for CMake. + +Most the Evaluation Kit and boards are shipped with a CMSIS-DAP +compatible debug probe. However, at the time of writing, the necessary flashing +algorithms for OpenOCD have not yet been incorporated into the OpenOCD master +branch. To utilize the provided debug probes, please install the bundled MSDK +package which includes the appropriate OpenOCD modifications. To leverage this +OpenOCD instance, run the `-openocd` CMake +target. diff --git a/hw/bsp/maxim/boards/apard32690/board.cmake b/hw/bsp/maxim/boards/apard32690/board.cmake new file mode 100644 index 000000000..a03d05f8d --- /dev/null +++ b/hw/bsp/maxim/boards/apard32690/board.cmake @@ -0,0 +1,4 @@ +set(MAX_DEVICE max32690) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/max32690/boards/apard32690/board.h b/hw/bsp/maxim/boards/apard32690/board.h similarity index 100% rename from hw/bsp/max32690/boards/apard32690/board.h rename to hw/bsp/maxim/boards/apard32690/board.h diff --git a/hw/bsp/maxim/boards/max32650evkit/board.cmake b/hw/bsp/maxim/boards/max32650evkit/board.cmake new file mode 100644 index 000000000..59721e756 --- /dev/null +++ b/hw/bsp/maxim/boards/max32650evkit/board.cmake @@ -0,0 +1,8 @@ +set(MAX_DEVICE max32650) + +function(update_board TARGET) +endfunction() + +function(prepare_image TARGET_IN) + #No signing required +endfunction() diff --git a/hw/bsp/max32650/boards/max32650evkit/board.h b/hw/bsp/maxim/boards/max32650evkit/board.h similarity index 100% rename from hw/bsp/max32650/boards/max32650evkit/board.h rename to hw/bsp/maxim/boards/max32650evkit/board.h diff --git a/hw/bsp/maxim/boards/max32650fthr/board.cmake b/hw/bsp/maxim/boards/max32650fthr/board.cmake new file mode 100644 index 000000000..59721e756 --- /dev/null +++ b/hw/bsp/maxim/boards/max32650fthr/board.cmake @@ -0,0 +1,8 @@ +set(MAX_DEVICE max32650) + +function(update_board TARGET) +endfunction() + +function(prepare_image TARGET_IN) + #No signing required +endfunction() diff --git a/hw/bsp/max32650/boards/max32650fthr/board.h b/hw/bsp/maxim/boards/max32650fthr/board.h similarity index 100% rename from hw/bsp/max32650/boards/max32650fthr/board.h rename to hw/bsp/maxim/boards/max32650fthr/board.h diff --git a/hw/bsp/max32650/boards/max32651evkit/board.cmake b/hw/bsp/maxim/boards/max32651evkit/board.cmake similarity index 81% rename from hw/bsp/max32650/boards/max32651evkit/board.cmake rename to hw/bsp/maxim/boards/max32651evkit/board.cmake index bd8077a42..773989126 100644 --- a/hw/bsp/max32650/boards/max32651evkit/board.cmake +++ b/hw/bsp/maxim/boards/max32651evkit/board.cmake @@ -1,22 +1,23 @@ -# Use the secure linker file -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/max32651.ld) +set(MAX_DEVICE max32650) -function(update_board_extras TARGET) +# Use the secure linker file +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/max32651.ld) + +function(update_board TARGET) # for the signed target, need to add the __SLA_FWK__ define target_compile_definitions(${TARGET} PUBLIC __SLA_FWK__ ) endfunction() -function(prepare_image TARGET_IN) - #For the signed target, set up a POST_BUILD command to sign the elf file once - #created +function(sign_image TARGET_IN) + #For the signed target, set up a POST_BUILD command to sign the elf file once created if((WIN32) OR (MINGW) OR (MSYS)) set(SIGN_EXE "sign_app.exe") else() set(SIGN_EXE "sign_app") endif() - set(MCU_PATH "${TOP}/hw/mcu/analog/max32/") + set(MCU_PATH "${TOP}/hw/mcu/analog/msdk/") # Custom POST_BUILD command add_custom_command( diff --git a/hw/bsp/max32650/boards/max32651evkit/board.h b/hw/bsp/maxim/boards/max32651evkit/board.h similarity index 100% rename from hw/bsp/max32650/boards/max32651evkit/board.h rename to hw/bsp/maxim/boards/max32651evkit/board.h diff --git a/hw/bsp/maxim/boards/max32666evkit/board.cmake b/hw/bsp/maxim/boards/max32666evkit/board.cmake new file mode 100644 index 000000000..e7116b603 --- /dev/null +++ b/hw/bsp/maxim/boards/max32666evkit/board.cmake @@ -0,0 +1,4 @@ +set(MAX_DEVICE max32665) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/max32666/boards/max32666evkit/board.h b/hw/bsp/maxim/boards/max32666evkit/board.h similarity index 100% rename from hw/bsp/max32666/boards/max32666evkit/board.h rename to hw/bsp/maxim/boards/max32666evkit/board.h diff --git a/hw/bsp/maxim/boards/max32666fthr/board.cmake b/hw/bsp/maxim/boards/max32666fthr/board.cmake new file mode 100644 index 000000000..e7116b603 --- /dev/null +++ b/hw/bsp/maxim/boards/max32666fthr/board.cmake @@ -0,0 +1,4 @@ +set(MAX_DEVICE max32665) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/max32666/boards/max32666fthr/board.h b/hw/bsp/maxim/boards/max32666fthr/board.h similarity index 100% rename from hw/bsp/max32666/boards/max32666fthr/board.h rename to hw/bsp/maxim/boards/max32666fthr/board.h diff --git a/hw/bsp/maxim/boards/max32690evkit/board.cmake b/hw/bsp/maxim/boards/max32690evkit/board.cmake new file mode 100644 index 000000000..a03d05f8d --- /dev/null +++ b/hw/bsp/maxim/boards/max32690evkit/board.cmake @@ -0,0 +1,4 @@ +set(MAX_DEVICE max32690) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/max32690/boards/max32690evkit/board.h b/hw/bsp/maxim/boards/max32690evkit/board.h similarity index 100% rename from hw/bsp/max32690/boards/max32690evkit/board.h rename to hw/bsp/maxim/boards/max32690evkit/board.h diff --git a/hw/bsp/maxim/boards/max78002evkit/board.cmake b/hw/bsp/maxim/boards/max78002evkit/board.cmake new file mode 100644 index 000000000..dd4c3c215 --- /dev/null +++ b/hw/bsp/maxim/boards/max78002evkit/board.cmake @@ -0,0 +1,4 @@ +set(MAX_DEVICE max78002) + +function(update_board TARGET) +endfunction() diff --git a/hw/bsp/max78002/boards/max78002evkit/board.h b/hw/bsp/maxim/boards/max78002evkit/board.h similarity index 100% rename from hw/bsp/max78002/boards/max78002evkit/board.h rename to hw/bsp/maxim/boards/max78002evkit/board.h diff --git a/hw/bsp/max32666/family.c b/hw/bsp/maxim/family.c similarity index 77% rename from hw/bsp/max32666/family.c rename to hw/bsp/maxim/family.c index 05306c6c9..0ef6b8c4d 100644 --- a/hw/bsp/max32666/family.c +++ b/hw/bsp/maxim/family.c @@ -35,7 +35,9 @@ #include "gpio.h" #include "mxc_sys.h" +#if __has_include("mcr_regs.h") #include "mcr_regs.h" +#endif #include "mxc_device.h" #include "uart.h" @@ -88,16 +90,45 @@ void board_init(void) { MXC_GPIO_Config(&gpioConfig); // UART +#if MAX_PERIPH_ID == 14 MXC_UART_Init(ConsoleUart, CFG_BOARD_UART_BAUDRATE, UART_MAP); +#elif MAX_PERIPH_ID == 18 || MAX_PERIPH_ID == 87 + MXC_UART_Init(ConsoleUart, CFG_BOARD_UART_BAUDRATE, MXC_UART_IBRO_CLK); + #if MAX_PERIPH_ID == 87 + UART_PORT->vssel |= UART_VDDIO_BITS; // Set necessary bits to 3.3V + #endif +#endif //USB +#if defined(MAX32650) // Startup the HIRC96M clock if it's not on already - if (!(MXC_GCR->clkcn & MXC_F_GCR_CLKCN_HIRC96M_EN)) { - MXC_GCR->clkcn |= MXC_F_GCR_CLKCN_HIRC96M_EN; + if (!(MXC_GCR->clk_ctrl & MXC_F_GCR_CLK_CTRL_HIRC96_EN)) { + MXC_GCR->clk_ctrl |= MXC_F_GCR_CLK_CTRL_HIRC96_EN; + MXC_SYS_Clock_Timeout(MXC_F_GCR_CLK_CTRL_HIRC96_RDY); } - MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); MXC_SYS_Reset_Periph(MXC_SYS_RESET_USB); + +#elif defined(MAX32665) || defined(MAX32666) + // Startup the HIRC96M clock if it's not on already + if (!(MXC_GCR->clkcn & MXC_F_GCR_CLKCN_HIRC96M_EN)) { + MXC_GCR->clkcn |= MXC_F_GCR_CLKCN_HIRC96M_EN; + } + MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); + MXC_SYS_Reset_Periph(MXC_SYS_RESET_USB); + +#elif defined(MAX32690) + MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IPO); + MXC_MCR->ldoctrl |= MXC_F_MCR_LDOCTRL_0P9EN; + MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); + MXC_SYS_Reset_Periph(MXC_SYS_RESET0_USB); + +# elif defined(MAX78002) + MXC_MCR->ldoctrl |= MXC_F_MCR_LDOCTRL_0P9EN; + MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); +#else + #error "Unsupported MAXIM MCU for board_dfu_init" +#endif } //--------------------------------------------------------------------+ @@ -121,13 +152,18 @@ uint32_t board_button_read(void) { } size_t board_get_unique_id(uint8_t id[], size_t max_len) { - uint8_t hw_id[MXC_SYS_USN_CHECKSUM_LEN];//USN Buffer - /* All other 2nd parameter is optional checksum buffer */ - MXC_SYS_GetUSN(hw_id, NULL); +#if defined(MAX32650) + // USN is 13 bytes on this device + MXC_SYS_GetUSN(id, 13); + return 13; +#else + uint8_t hw_id[MXC_SYS_USN_CHECKSUM_LEN]; //USN Buffer + MXC_SYS_GetUSN(hw_id, NULL); // 2nd parameter is optional checksum buffer size_t act_len = TU_MIN(max_len, MXC_SYS_USN_LEN); memcpy(id, hw_id, act_len); return act_len; +#endif } int board_uart_read(uint8_t *buf, int len) { diff --git a/hw/bsp/maxim/family.cmake b/hw/bsp/maxim/family.cmake new file mode 100644 index 000000000..1fd5215ba --- /dev/null +++ b/hw/bsp/maxim/family.cmake @@ -0,0 +1,205 @@ +include_guard() + +# stub: overridden by board.cmake if needed +function(sign_image TARGET_IN) +endfunction() + +set(MSDK_LIB ${TOP}/hw/mcu/analog/msdk/Libraries) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +cmake_print_variables(MAX_DEVICE) +string(TOUPPER ${MAX_DEVICE} MAX_DEVICE_UPPER) + +set(JLINK_DEVICE ${MAX_DEVICE}) +set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -f target/${MAX_DEVICE}.cfg") + +set(FAMILY_MCUS ${MAX_DEVICE_UPPER} CACHE INTERNAL "") + +if (${MAX_DEVICE} STREQUAL "max32650") + set(PERIPH_ID 10) + set(PERIPH_SUFFIX "me") +elseif (${MAX_DEVICE} STREQUAL "max32665" OR ${MAX_DEVICE} STREQUAL "max32666") + set(PERIPH_ID 14) + set(PERIPH_SUFFIX "me") +elseif (${MAX_DEVICE} STREQUAL "max32690") + set(PERIPH_ID 18) + set(PERIPH_SUFFIX "me") +elseif (${MAX_DEVICE} STREQUAL "max78002") + set(PERIPH_ID 87) + set(PERIPH_SUFFIX "ai") +else() + message(FATAL_ERROR "Unsupported MAX device: ${MAX_DEVICE}") +endif() + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + # Startup & Linker script + set(STARTUP_FILE_GNU ${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Source/GCC/startup_${MAX_DEVICE}.S) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MAX_DEVICE}.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + + # Common + add_library(${BOARD_TARGET} STATIC + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Source/heap.c + ${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Source/system_${MAX_DEVICE}.c + ${MSDK_LIB}/PeriphDrivers/Source/SYS/mxc_assert.c + ${MSDK_LIB}/PeriphDrivers/Source/SYS/mxc_delay.c + ${MSDK_LIB}/PeriphDrivers/Source/SYS/mxc_lock.c + ${MSDK_LIB}/PeriphDrivers/Source/SYS/nvic_table.c + ${MSDK_LIB}/PeriphDrivers/Source/SYS/pins_${PERIPH_SUFFIX}${PERIPH_ID}.c + ${MSDK_LIB}/PeriphDrivers/Source/SYS/sys_${PERIPH_SUFFIX}${PERIPH_ID}.c + ${MSDK_LIB}/PeriphDrivers/Source/FLC/flc_common.c + ${MSDK_LIB}/PeriphDrivers/Source/FLC/flc_${PERIPH_SUFFIX}${PERIPH_ID}.c + ${MSDK_LIB}/PeriphDrivers/Source/FLC/flc_reva.c + ${MSDK_LIB}/PeriphDrivers/Source/GPIO/gpio_common.c + ${MSDK_LIB}/PeriphDrivers/Source/GPIO/gpio_${PERIPH_SUFFIX}${PERIPH_ID}.c + ${MSDK_LIB}/PeriphDrivers/Source/GPIO/gpio_reva.c + ${MSDK_LIB}/PeriphDrivers/Source/ICC/icc_${PERIPH_SUFFIX}${PERIPH_ID}.c + ${MSDK_LIB}/PeriphDrivers/Source/ICC/icc_reva.c + ${MSDK_LIB}/PeriphDrivers/Source/UART/uart_common.c + ${MSDK_LIB}/PeriphDrivers/Source/UART/uart_${PERIPH_SUFFIX}${PERIPH_ID}.c + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${MSDK_LIB}/CMSIS/5.9.0/Core/Include + ${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Include + ${MSDK_LIB}/PeriphDrivers/Include/${MAX_DEVICE_UPPER} + ${MSDK_LIB}/PeriphDrivers/Source/SYS + ${MSDK_LIB}/PeriphDrivers/Source/GPIO + ${MSDK_LIB}/PeriphDrivers/Source/ICC + ${MSDK_LIB}/PeriphDrivers/Source/FLC + ${MSDK_LIB}/PeriphDrivers/Source/UART + ) + + # device specific + if (${MAX_DEVICE} STREQUAL "max32650" OR + ${MAX_DEVICE} STREQUAL "max32665" OR ${MAX_DEVICE} STREQUAL "max32666") + target_sources(${BOARD_TARGET} PRIVATE + ${MSDK_LIB}/PeriphDrivers/Source/ICC/icc_common.c + ${MSDK_LIB}/PeriphDrivers/Source/TPU/tpu_${PERIPH_SUFFIX}${PERIPH_ID}.c + ${MSDK_LIB}/PeriphDrivers/Source/TPU/tpu_reva.c + ${MSDK_LIB}/PeriphDrivers/Source/UART/uart_reva.c + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${MSDK_LIB}/PeriphDrivers/Source/TPU + ) + elseif (${MAX_DEVICE} STREQUAL "max32690") + target_sources(${BOARD_TARGET} PRIVATE + ${MSDK_LIB}/PeriphDrivers/Source/CTB/ctb_${PERIPH_SUFFIX}${PERIPH_ID}.c + ${MSDK_LIB}/PeriphDrivers/Source/CTB/ctb_reva.c + ${MSDK_LIB}/PeriphDrivers/Source/CTB/ctb_common.c + ${MSDK_LIB}/PeriphDrivers/Source/UART/uart_revb.c + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${MSDK_LIB}/PeriphDrivers/Source/CTB + ) + elseif (${MAX_DEVICE} STREQUAL "max78002") + target_sources(${BOARD_TARGET} PRIVATE + ${MSDK_LIB}/PeriphDrivers/Source/AES/aes_${PERIPH_SUFFIX}${PERIPH_ID}.c + ${MSDK_LIB}/PeriphDrivers/Source/AES/aes_revb.c + ${MSDK_LIB}/PeriphDrivers/Source/TRNG/trng_${PERIPH_SUFFIX}${PERIPH_ID}.c + ${MSDK_LIB}/PeriphDrivers/Source/TRNG/trng_revb.c + ${MSDK_LIB}/PeriphDrivers/Source/UART/uart_revb.c + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${MSDK_LIB}/PeriphDrivers/Source/AES + ${MSDK_LIB}/PeriphDrivers/Source/TRNG + ) + else() + message(FATAL_ERROR "Unsupported MAX device: ${MAX_DEVICE}") + endif() + + target_compile_definitions(${BOARD_TARGET} PUBLIC + TARGET=${MAX_DEVICE_UPPER} + TARGET_REV=0x4131 + MXC_ASSERT_ENABLE + ${MAX_DEVICE_UPPER} + IAR_PRAGMAS=0 + FLASH_BOOT_SIZE=${FLASH_BOOT_SIZE} + MAX_PERIPH_ID=${PERIPH_ID} + ) + + target_compile_definitions(${TARGET} PUBLIC + TARGET=MAX32690 + TARGET_REV=0x4131 + MXC_ASSERT_ENABLE + MAX32690 + BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + ) + + target_compile_options(${BOARD_TARGET} PRIVATE + -Wno-error=strict-prototypes + ) + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_${MAX_DEVICE_UPPER}) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/mentor/musb/dcd_musb.c + ) + target_compile_options(${TARGET} PRIVATE + -Wno-error=strict-prototypes + ) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) + + sign_image(${TARGET}) # for secured device such as max32651 + family_flash_openocd_adi(${TARGET}) +endfunction() diff --git a/hw/bsp/max32650/boards/max32650evkit/max32650.ld b/hw/bsp/maxim/linker/max32650.ld similarity index 100% rename from hw/bsp/max32650/boards/max32650evkit/max32650.ld rename to hw/bsp/maxim/linker/max32650.ld diff --git a/hw/bsp/max32650/boards/max32651evkit/max32651.ld b/hw/bsp/maxim/linker/max32651.ld similarity index 100% rename from hw/bsp/max32650/boards/max32651evkit/max32651.ld rename to hw/bsp/maxim/linker/max32651.ld diff --git a/hw/bsp/max32666/max32666.ld b/hw/bsp/maxim/linker/max32665.ld similarity index 100% rename from hw/bsp/max32666/max32666.ld rename to hw/bsp/maxim/linker/max32665.ld diff --git a/hw/bsp/max32690/max32690.ld b/hw/bsp/maxim/linker/max32690.ld similarity index 100% rename from hw/bsp/max32690/max32690.ld rename to hw/bsp/maxim/linker/max32690.ld diff --git a/hw/bsp/max78002/max78002.ld b/hw/bsp/maxim/linker/max78002.ld similarity index 100% rename from hw/bsp/max78002/max78002.ld rename to hw/bsp/maxim/linker/max78002.ld diff --git a/tools/get_deps.py b/tools/get_deps.py index 1ce8be6c7..635edaa66 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -25,9 +25,9 @@ deps_optional = { 'hw/mcu/allwinner': ['https://github.com/hathach/allwinner_driver.git', '8e5e89e8e132c0fd90e72d5422e5d3d68232b756', 'fc100s'], - 'hw/mcu/analog/max32' : ['https://github.com/analogdevicesinc/msdk.git', + 'hw/mcu/analog/msdk' : ['https://github.com/analogdevicesinc/msdk.git', 'b20b398d3e5e2007594e54a74ba3d2a2e50ddd75', - 'max32650 max32666 max32690 max78002'], + 'maxim'], 'hw/mcu/bridgetek/ft9xx/ft90x-sdk': ['https://github.com/BRTSG-FOSS/ft90x-sdk.git', '91060164afe239fcb394122e8bf9eb24d3194eb1', 'brtmm90x'], From 1be7b8f781d34098b4af74cbcf06916287addf95 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 10 Jun 2025 23:29:45 +0700 Subject: [PATCH 210/382] remove max32666fthr from hil pool --- test/hil/tinyusb.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json index 8a835e4c0..11b118cea 100644 --- a/test/hil/tinyusb.json +++ b/test/hil/tinyusb.json @@ -46,18 +46,6 @@ "args": "-device nrf52840_xxaa" } }, - { - "name": "max32666fthr", - "uid": "0C81464124010B20FF0A08CC2C", - "tests": { - "device": true, "host": false, "dual": false - }, - "flasher": { - "name": "openocd_adi", - "uid": "E6614C311B597D32", - "args": "-f interface/cmsis-dap.cfg -f target/max32665.cfg" - } - }, { "name": "metro_m4_express", "uid": "9995AD485337433231202020FF100A34", @@ -211,6 +199,18 @@ } ], "boards-skip": [ + { + "name": "max32666fthr", + "uid": "0C81464124010B20FF0A08CC2C", + "tests": { + "device": true, "host": false, "dual": false + }, + "flasher": { + "name": "openocd_adi", + "uid": "E6614C311B597D32", + "args": "-f interface/cmsis-dap.cfg -f target/max32665.cfg" + } + }, { "name": "stm32f769disco", "uid": "21002F000F51363531383437", From 41e615d7c2c0588793bcf85f9cb5207e82a9e6f6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 11 Jun 2025 12:00:20 +0700 Subject: [PATCH 211/382] add make build for maxim --- examples/build_system/make/make.mk | 5 +- hw/bsp/family_support.cmake | 5 + hw/bsp/maxim/README.md | 2 +- hw/bsp/maxim/boards/apard32690/board.h | 3 +- hw/bsp/maxim/boards/apard32690/board.mk | 1 + hw/bsp/maxim/boards/max32650evkit/board.h | 3 +- hw/bsp/maxim/boards/max32650evkit/board.mk | 1 + hw/bsp/maxim/boards/max32650fthr/board.h | 3 +- hw/bsp/maxim/boards/max32650fthr/board.mk | 1 + hw/bsp/maxim/boards/max32651evkit/board.h | 3 +- hw/bsp/maxim/boards/max32651evkit/board.mk | 7 + hw/bsp/maxim/boards/max32666evkit/board.h | 3 +- hw/bsp/maxim/boards/max32666evkit/board.mk | 1 + hw/bsp/maxim/boards/max32666fthr/board.h | 3 +- hw/bsp/maxim/boards/max32666fthr/board.mk | 1 + hw/bsp/maxim/boards/max32690evkit/board.h | 5 +- hw/bsp/maxim/boards/max32690evkit/board.mk | 1 + hw/bsp/maxim/boards/max78002evkit/board.h | 3 +- hw/bsp/maxim/boards/max78002evkit/board.mk | 1 + hw/bsp/maxim/family.cmake | 11 +- hw/bsp/maxim/family.mk | 190 +++++++++++++++++++++ 21 files changed, 224 insertions(+), 29 deletions(-) create mode 100644 hw/bsp/maxim/boards/apard32690/board.mk create mode 100644 hw/bsp/maxim/boards/max32650evkit/board.mk create mode 100644 hw/bsp/maxim/boards/max32650fthr/board.mk create mode 100644 hw/bsp/maxim/boards/max32651evkit/board.mk create mode 100644 hw/bsp/maxim/boards/max32666evkit/board.mk create mode 100644 hw/bsp/maxim/boards/max32666fthr/board.mk create mode 100644 hw/bsp/maxim/boards/max32690evkit/board.mk create mode 100644 hw/bsp/maxim/boards/max78002evkit/board.mk create mode 100644 hw/bsp/maxim/family.mk diff --git a/examples/build_system/make/make.mk b/examples/build_system/make/make.mk index 3101b66b9..dbc73903e 100644 --- a/examples/build_system/make/make.mk +++ b/examples/build_system/make/make.mk @@ -2,6 +2,9 @@ # Common make definition for all examples # --------------------------------------- +# upper helper function +to_upper = $(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,$(subst z,Z,$(subst -,_,$(1)))))))))))))))))))))))))))) + #------------------------------------------------------------- # Toolchain # Can be changed via TOOLCHAIN=gcc|iar or CC=arm-none-eabi-gcc|iccarm|clang @@ -109,7 +112,7 @@ INC += \ $(TOP)/$(FAMILY_PATH) \ $(TOP)/src \ -BOARD_UPPER = $(subst a,A,$(subst b,B,$(subst c,C,$(subst d,D,$(subst e,E,$(subst f,F,$(subst g,G,$(subst h,H,$(subst i,I,$(subst j,J,$(subst k,K,$(subst l,L,$(subst m,M,$(subst n,N,$(subst o,O,$(subst p,P,$(subst q,Q,$(subst r,R,$(subst s,S,$(subst t,T,$(subst u,U,$(subst v,V,$(subst w,W,$(subst x,X,$(subst y,Y,$(subst z,Z,$(subst -,_,$(BOARD)))))))))))))))))))))))))))) +BOARD_UPPER = $(call to_upper,$(BOARD)) CFLAGS += -DBOARD_$(BOARD_UPPER) ifdef CFLAGS_CLI diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index ac1276f7d..3325dbbf0 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -38,6 +38,11 @@ if (NOT DEFINED TOOLCHAIN) set(TOOLCHAIN gcc) endif () +# Optimization +if (NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "") + set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Build type" FORCE) +endif () + #------------------------------------------------------------- # FAMILY and BOARD #------------------------------------------------------------- diff --git a/hw/bsp/maxim/README.md b/hw/bsp/maxim/README.md index c4b9f0bfc..e2983e899 100644 --- a/hw/bsp/maxim/README.md +++ b/hw/bsp/maxim/README.md @@ -39,5 +39,5 @@ compatible debug probe. However, at the time of writing, the necessary flashing algorithms for OpenOCD have not yet been incorporated into the OpenOCD master branch. To utilize the provided debug probes, please install the bundled MSDK package which includes the appropriate OpenOCD modifications. To leverage this -OpenOCD instance, run the `-openocd` CMake +OpenOCD instance, run the `flash-msdk` Makefile rule, or `-openocd` CMake target. diff --git a/hw/bsp/maxim/boards/apard32690/board.h b/hw/bsp/maxim/boards/apard32690/board.h index 87b9c4e88..19f74bf56 100644 --- a/hw/bsp/maxim/boards/apard32690/board.h +++ b/hw/bsp/maxim/boards/apard32690/board.h @@ -32,8 +32,7 @@ #ifndef BOARD_H_ #define BOARD_H_ -#include "gpio.h" -#include "mxc_sys.h" +#include "max32690.h" #ifdef __cplusplus extern "C" { diff --git a/hw/bsp/maxim/boards/apard32690/board.mk b/hw/bsp/maxim/boards/apard32690/board.mk new file mode 100644 index 000000000..d8a0c9cae --- /dev/null +++ b/hw/bsp/maxim/boards/apard32690/board.mk @@ -0,0 +1 @@ +MAX_DEVICE = max32690 diff --git a/hw/bsp/maxim/boards/max32650evkit/board.h b/hw/bsp/maxim/boards/max32650evkit/board.h index 65ed2659e..9c1f55f8e 100644 --- a/hw/bsp/maxim/boards/max32650evkit/board.h +++ b/hw/bsp/maxim/boards/max32650evkit/board.h @@ -32,8 +32,7 @@ #ifndef BOARD_H_ #define BOARD_H_ -#include "gpio.h" -#include "mxc_sys.h" +#include "max32650.h" #ifdef __cplusplus extern "C" { diff --git a/hw/bsp/maxim/boards/max32650evkit/board.mk b/hw/bsp/maxim/boards/max32650evkit/board.mk new file mode 100644 index 000000000..3a4108005 --- /dev/null +++ b/hw/bsp/maxim/boards/max32650evkit/board.mk @@ -0,0 +1 @@ +MAX_DEVICE = max32650 diff --git a/hw/bsp/maxim/boards/max32650fthr/board.h b/hw/bsp/maxim/boards/max32650fthr/board.h index 755fa15b5..af0fa1c39 100644 --- a/hw/bsp/maxim/boards/max32650fthr/board.h +++ b/hw/bsp/maxim/boards/max32650fthr/board.h @@ -32,8 +32,7 @@ #ifndef BOARD_H_ #define BOARD_H_ -#include "gpio.h" -#include "mxc_sys.h" +#include "max32650.h" #ifdef __cplusplus extern "C" { diff --git a/hw/bsp/maxim/boards/max32650fthr/board.mk b/hw/bsp/maxim/boards/max32650fthr/board.mk new file mode 100644 index 000000000..3a4108005 --- /dev/null +++ b/hw/bsp/maxim/boards/max32650fthr/board.mk @@ -0,0 +1 @@ +MAX_DEVICE = max32650 diff --git a/hw/bsp/maxim/boards/max32651evkit/board.h b/hw/bsp/maxim/boards/max32651evkit/board.h index 0b49ff309..dbf2a4b7c 100644 --- a/hw/bsp/maxim/boards/max32651evkit/board.h +++ b/hw/bsp/maxim/boards/max32651evkit/board.h @@ -32,8 +32,7 @@ #ifndef BOARD_H_ #define BOARD_H_ -#include "gpio.h" -#include "mxc_sys.h" +#include "max32650.h" #ifdef __cplusplus extern "C" { diff --git a/hw/bsp/maxim/boards/max32651evkit/board.mk b/hw/bsp/maxim/boards/max32651evkit/board.mk new file mode 100644 index 000000000..5d4971148 --- /dev/null +++ b/hw/bsp/maxim/boards/max32651evkit/board.mk @@ -0,0 +1,7 @@ +MAX_DEVICE = max32650 + +# Use the secure linker file +LD_FILE = $(FAMILY_PATH)/linker/max32651.ld + +# Let the family script know the build needs to be signed +SIGNED_BUILD := 1 diff --git a/hw/bsp/maxim/boards/max32666evkit/board.h b/hw/bsp/maxim/boards/max32666evkit/board.h index 54589444d..42965d3c5 100644 --- a/hw/bsp/maxim/boards/max32666evkit/board.h +++ b/hw/bsp/maxim/boards/max32666evkit/board.h @@ -32,8 +32,7 @@ #ifndef BOARD_H_ #define BOARD_H_ -#include "gpio.h" -#include "mxc_sys.h" +#include "max32665.h" #ifdef __cplusplus extern "C" { diff --git a/hw/bsp/maxim/boards/max32666evkit/board.mk b/hw/bsp/maxim/boards/max32666evkit/board.mk new file mode 100644 index 000000000..a1cf3045d --- /dev/null +++ b/hw/bsp/maxim/boards/max32666evkit/board.mk @@ -0,0 +1 @@ +MAX_DEVICE = max32665 diff --git a/hw/bsp/maxim/boards/max32666fthr/board.h b/hw/bsp/maxim/boards/max32666fthr/board.h index 0caea5934..fbb217949 100644 --- a/hw/bsp/maxim/boards/max32666fthr/board.h +++ b/hw/bsp/maxim/boards/max32666fthr/board.h @@ -32,8 +32,7 @@ #ifndef BOARD_H_ #define BOARD_H_ -#include "gpio.h" -#include "mxc_sys.h" +#include "max32665.h" #ifdef __cplusplus extern "C" { diff --git a/hw/bsp/maxim/boards/max32666fthr/board.mk b/hw/bsp/maxim/boards/max32666fthr/board.mk new file mode 100644 index 000000000..a1cf3045d --- /dev/null +++ b/hw/bsp/maxim/boards/max32666fthr/board.mk @@ -0,0 +1 @@ +MAX_DEVICE = max32665 diff --git a/hw/bsp/maxim/boards/max32690evkit/board.h b/hw/bsp/maxim/boards/max32690evkit/board.h index aa8dbb1de..41c73621f 100644 --- a/hw/bsp/maxim/boards/max32690evkit/board.h +++ b/hw/bsp/maxim/boards/max32690evkit/board.h @@ -32,13 +32,12 @@ #ifndef BOARD_H_ #define BOARD_H_ -#include "gpio.h" -#include "mxc_sys.h" - #ifdef __cplusplus extern "C" { #endif +#include "max32690.h" + // LED #define LED_PORT MXC_GPIO0 #define LED_PIN MXC_GPIO_PIN_14 diff --git a/hw/bsp/maxim/boards/max32690evkit/board.mk b/hw/bsp/maxim/boards/max32690evkit/board.mk new file mode 100644 index 000000000..d8a0c9cae --- /dev/null +++ b/hw/bsp/maxim/boards/max32690evkit/board.mk @@ -0,0 +1 @@ +MAX_DEVICE = max32690 diff --git a/hw/bsp/maxim/boards/max78002evkit/board.h b/hw/bsp/maxim/boards/max78002evkit/board.h index 85d55d7de..8c1fc13d4 100644 --- a/hw/bsp/maxim/boards/max78002evkit/board.h +++ b/hw/bsp/maxim/boards/max78002evkit/board.h @@ -32,8 +32,7 @@ #ifndef BOARD_H_ #define BOARD_H_ -#include "gpio.h" -#include "mxc_sys.h" +#include "max78002.h" #ifdef __cplusplus extern "C" { diff --git a/hw/bsp/maxim/boards/max78002evkit/board.mk b/hw/bsp/maxim/boards/max78002evkit/board.mk new file mode 100644 index 000000000..b19e95187 --- /dev/null +++ b/hw/bsp/maxim/boards/max78002evkit/board.mk @@ -0,0 +1 @@ +MAX_DEVICE = max78002 diff --git a/hw/bsp/maxim/family.cmake b/hw/bsp/maxim/family.cmake index 1fd5215ba..75daec753 100644 --- a/hw/bsp/maxim/family.cmake +++ b/hw/bsp/maxim/family.cmake @@ -13,8 +13,8 @@ include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) -cmake_print_variables(MAX_DEVICE) string(TOUPPER ${MAX_DEVICE} MAX_DEVICE_UPPER) +cmake_print_variables(MAX_DEVICE MAX_DEVICE_UPPER) set(JLINK_DEVICE ${MAX_DEVICE}) set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -f target/${MAX_DEVICE}.cfg") @@ -132,18 +132,9 @@ function(add_board_target BOARD_TARGET) MXC_ASSERT_ENABLE ${MAX_DEVICE_UPPER} IAR_PRAGMAS=0 - FLASH_BOOT_SIZE=${FLASH_BOOT_SIZE} MAX_PERIPH_ID=${PERIPH_ID} - ) - - target_compile_definitions(${TARGET} PUBLIC - TARGET=MAX32690 - TARGET_REV=0x4131 - MXC_ASSERT_ENABLE - MAX32690 BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED ) - target_compile_options(${BOARD_TARGET} PRIVATE -Wno-error=strict-prototypes ) diff --git a/hw/bsp/maxim/family.mk b/hw/bsp/maxim/family.mk new file mode 100644 index 000000000..3ddf8cf39 --- /dev/null +++ b/hw/bsp/maxim/family.mk @@ -0,0 +1,190 @@ +MSDK_LIB = hw/mcu/analog/msdk/Libraries + +# Add any board specific make rules +include $(TOP)/$(BOARD_PATH)/board.mk + +CPU_CORE ?= cortex-m4 +PORT ?= 0 +JLINK_DEVICE = ${MAX_DEVICE} +MAX_DEVICE_UPPER = $(call to_upper,${MAX_DEVICE}) + +ifeq ($(MAX_DEVICE),max32650) + PERIPH_ID = 10 + PERIPH_SUFFIX = me +endif + +ifneq ($(filter $(MAX_DEVICE),max32665 max32666),) + PERIPH_ID = 14 + PERIPH_SUFFIX = me +endif + +ifeq ($(MAX_DEVICE),max32690) + PERIPH_ID = 18 + PERIPH_SUFFIX = me +endif + +ifeq ($(MAX_DEVICE),max78002) + PERIPH_ID = 87 + PERIPH_SUFFIX = ai +endif + +ifndef PERIPH_ID + $(error Unsupported MAX device: ${MAX_DEVICE}) +endif + +# Configure the flash rule. By default, use JLink. +SIGNED_BUILD ?= 0 +DEFAULT_FLASH = flash-jlink + +# -------------- +# Compiler Flags +# -------------- +CFLAGS += \ + -DTARGET=${MAX_DEVICE_UPPER}\ + -DTARGET_REV=0x4131 \ + -DMXC_ASSERT_ENABLE \ + -D${MAX_DEVICE_UPPER} \ + -DIAR_PRAGMAS=0 \ + -DMAX_PERIPH_ID=${PERIPH_ID} \ + -DCFG_TUSB_MCU=OPT_MCU_${MAX_DEVICE_UPPER} \ + -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + +# mcu driver cause following warnings +CFLAGS += \ + -Wno-error=old-style-declaration \ + -Wno-error=redundant-decls \ + -Wno-error=strict-prototypes \ + -Wno-error=unused-parameter \ + -Wno-error=cast-align \ + -Wno-error=cast-qual \ + -Wno-error=sign-compare \ + -Wno-error=enum-conversion \ + +LDFLAGS_GCC += -nostartfiles --specs=nosys.specs --specs=nano.specs +LD_FILE_GCC ?= $(FAMILY_PATH)/linker/${MAX_DEVICE}.ld + +# If the applications needs to be signed (for the MAX32651), sign it first and +# then need to use MSDK's OpenOCD to flash it +# Also need to include the __SLA_FWK__ define to enable the signed header into +# memory +ifeq ($(SIGNED_BUILD), 1) +# Extra definitions to build for the secure part +CFLAGS += -D__SLA_FWK__ +DEFAULT_FLASH := sign-build flash-msdk +endif + +# ----------------- +# Sources & Include +# ----------------- + +# common +SRC_C += \ + src/portable/mentor/musb/dcd_musb.c \ + ${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Source/heap.c \ + ${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Source/system_${MAX_DEVICE}.c \ + ${MSDK_LIB}/PeriphDrivers/Source/SYS/mxc_assert.c \ + ${MSDK_LIB}/PeriphDrivers/Source/SYS/mxc_delay.c \ + ${MSDK_LIB}/PeriphDrivers/Source/SYS/mxc_lock.c \ + ${MSDK_LIB}/PeriphDrivers/Source/SYS/nvic_table.c \ + ${MSDK_LIB}/PeriphDrivers/Source/SYS/pins_${PERIPH_SUFFIX}${PERIPH_ID}.c \ + ${MSDK_LIB}/PeriphDrivers/Source/SYS/sys_${PERIPH_SUFFIX}${PERIPH_ID}.c \ + ${MSDK_LIB}/PeriphDrivers/Source/FLC/flc_common.c \ + ${MSDK_LIB}/PeriphDrivers/Source/FLC/flc_${PERIPH_SUFFIX}${PERIPH_ID}.c \ + ${MSDK_LIB}/PeriphDrivers/Source/FLC/flc_reva.c \ + ${MSDK_LIB}/PeriphDrivers/Source/GPIO/gpio_common.c \ + ${MSDK_LIB}/PeriphDrivers/Source/GPIO/gpio_${PERIPH_SUFFIX}${PERIPH_ID}.c \ + ${MSDK_LIB}/PeriphDrivers/Source/GPIO/gpio_reva.c \ + ${MSDK_LIB}/PeriphDrivers/Source/ICC/icc_${PERIPH_SUFFIX}${PERIPH_ID}.c \ + ${MSDK_LIB}/PeriphDrivers/Source/ICC/icc_reva.c \ + ${MSDK_LIB}/PeriphDrivers/Source/UART/uart_common.c \ + ${MSDK_LIB}/PeriphDrivers/Source/UART/uart_${PERIPH_SUFFIX}${PERIPH_ID}.c \ + +SRC_S_GCC += ${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Source/GCC/startup_${MAX_DEVICE}.S + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/${MSDK_LIB}/CMSIS/5.9.0/Core/Include \ + $(TOP)/${MSDK_LIB}/CMSIS/Device/Maxim/${MAX_DEVICE_UPPER}/Include \ + $(TOP)/${MSDK_LIB}/PeriphDrivers/Include/${MAX_DEVICE_UPPER} \ + $(TOP)/${MSDK_LIB}/PeriphDrivers/Source/SYS \ + $(TOP)/${MSDK_LIB}/PeriphDrivers/Source/GPIO \ + $(TOP)/${MSDK_LIB}/PeriphDrivers/Source/ICC \ + $(TOP)/${MSDK_LIB}/PeriphDrivers/Source/FLC \ + $(TOP)/${MSDK_LIB}/PeriphDrivers/Source/UART \ + +# device specific +ifneq ($(filter $(MAX_DEVICE),max32650 max32665 max32666),) + SRC_C += \ + ${MSDK_LIB}/PeriphDrivers/Source/ICC/icc_common.c \ + ${MSDK_LIB}/PeriphDrivers/Source/TPU/tpu_${PERIPH_SUFFIX}${PERIPH_ID}.c \ + ${MSDK_LIB}/PeriphDrivers/Source/TPU/tpu_reva.c \ + ${MSDK_LIB}/PeriphDrivers/Source/UART/uart_reva.c \ + + INC += $(TOP)/${MSDK_LIB}/PeriphDrivers/Source/TPU +endif + +ifeq (${MAX_DEVICE},max32690) + SRC_C += \ + ${MSDK_LIB}/PeriphDrivers/Source/CTB/ctb_${PERIPH_SUFFIX}${PERIPH_ID}.c \ + ${MSDK_LIB}/PeriphDrivers/Source/CTB/ctb_reva.c \ + ${MSDK_LIB}/PeriphDrivers/Source/CTB/ctb_common.c \ + ${MSDK_LIB}/PeriphDrivers/Source/UART/uart_revb.c \ + + INC += ${TOP}/${MSDK_LIB}/PeriphDrivers/Source/CTB +endif + +ifeq (${MAX_DEVICE},max78002) + SRC_C += \ + ${MSDK_LIB}/PeriphDrivers/Source/AES/aes_${PERIPH_SUFFIX}${PERIPH_ID}.c \ + ${MSDK_LIB}/PeriphDrivers/Source/AES/aes_revb.c \ + ${MSDK_LIB}/PeriphDrivers/Source/TRNG/trng_${PERIPH_SUFFIX}${PERIPH_ID}.c \ + ${MSDK_LIB}/PeriphDrivers/Source/TRNG/trng_revb.c \ + ${MSDK_LIB}/PeriphDrivers/Source/UART/uart_revb.c \ + + INC += \ + ${TOP}/${MSDK_LIB}/PeriphDrivers/Source/AES \ + ${TOP}/${MSDK_LIB}/PeriphDrivers/Source/TRNG +endif + + +# The MAX32651EVKIT is pin for pin identical to the MAX32650EVKIT, however the +# MAX32651 has a secure bootloader which requires the image to be signed before +# loading into flash. All MAX32651EVKIT's have the same key for evaluation +# purposes, so create a special flash rule to sign the binary and flash using +# the MSDK. +MCU_PATH = $(TOP)/hw/mcu/analog/msdk/ +# Assume no extension for sign utility +SIGN_EXE = sign_app +ifeq ($(OS), Windows_NT) +# Must use .exe extension on Windows, since the binaries +# for Linux may live in the same place. +SIGN_EXE := sign_app.exe +else +UNAME = $(shell uname -s) +ifneq ($(findstring MSYS_NT,$(UNAME)),) +# Must also use .exe extension for MSYS2 +SIGN_EXE := sign_app.exe +endif +endif + +# Rule to sign the build. This will in-place modify the existing .elf file +# an populate the .sig section with the signature value +sign-build: $(BUILD)/$(PROJECT).elf + $(OBJCOPY) $(BUILD)/$(PROJECT).elf -R .sig -O binary $(BUILD)/$(PROJECT).bin + $(MCU_PATH)/Tools/SBT/bin/$(SIGN_EXE) -c MAX32651 \ + key_file="$(MCU_PATH)/Tools/SBT/devices/MAX32651/keys/maximtestcrk.key" \ + ca=$(BUILD)/$(PROJECT).bin sca=$(BUILD)/$(PROJECT).sbin + $(OBJCOPY) $(BUILD)/$(PROJECT).elf --update-section .sig=$(BUILD)/$(PROJECT).sig + +# Optional flash option when running within an installed MSDK to use OpenOCD +# Mainline OpenOCD does not yet have the MAX32's flash algorithm integrated. +# If the MSDK is installed, flash-msdk can be run to utilize the the modified +# openocd with the algorithms +MAXIM_PATH := $(subst \,/,$(MAXIM_PATH)) +flash-msdk: $(BUILD)/$(PROJECT).elf + $(MAXIM_PATH)/Tools/OpenOCD/openocd -s $(MAXIM_PATH)/Tools/OpenOCD/scripts \ + -f interface/cmsis-dap.cfg -f target/max32650.cfg \ + -c "program $(BUILD)/$(PROJECT).elf verify; init; reset; exit" + +# Configure the flash rule +flash: $(DEFAULT_FLASH) From 14124c1735507cdb40252f04a3580f80dd9952e9 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 11 Jun 2025 19:35:20 +0700 Subject: [PATCH 212/382] add h7rs to ci matrix --- .github/workflows/ci_set_matrix.py | 2 +- src/portable/synopsys/dwc2/dwc2_info.md | 116 ++++++++++++------------ src/portable/synopsys/dwc2/dwc2_info.py | 3 +- 3 files changed, 60 insertions(+), 61 deletions(-) diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index bccb07e3e..961e27a8f 100755 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -40,7 +40,7 @@ family_list = { "stm32f4": ["arm-gcc", "arm-clang", "arm-iar"], "stm32f7": ["arm-gcc", "arm-clang", "arm-iar"], "stm32g0 stm32g4 stm32h5": ["arm-gcc", "arm-clang", "arm-iar"], - "stm32h7": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32h7 stm32h7rs": ["arm-gcc", "arm-clang", "arm-iar"], "stm32l0 stm32l4": ["arm-gcc", "arm-clang", "arm-iar"], "stm32u5 stm32wb": ["arm-gcc", "arm-clang", "arm-iar"], "xmc4000": ["arm-gcc"], diff --git a/src/portable/synopsys/dwc2/dwc2_info.md b/src/portable/synopsys/dwc2/dwc2_info.md index 76bd251c7..54b3cae7c 100644 --- a/src/portable/synopsys/dwc2/dwc2_info.md +++ b/src/portable/synopsys/dwc2/dwc2_info.md @@ -1,58 +1,58 @@ -| | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5 HS | ST H7S3 HS | XMC4500 | GD32VF103 | -|:---------------------------|:----------------|:-------------|:--------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:-------------|:-------------|:-------------|:------------| -| GUID | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00005000 | 0x00AEC000 | 0x00001000 | -| GSNPSID | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54411A | 0x4F54292A | 0x00000000 | -| - specs version | 2.80a | 3.30a | 4.00a | 4.00a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 4.11a | 2.92a | 0.00W | -| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | -| GHWCFG2 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228FE052 | 0x228F5930 | 0x00000000 | -| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | noHNP noSRP | HNP SRP | HNP SRP | -| - arch | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | DMA internal | Slave only | -| - single_point | hub | hub | n/a | hub | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | hub | n/a | hub | -| - hs_phy_type | UTMI+ | n/a | n/a | UTMI+/ULPI | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | UTMI+ | n/a | n/a | -| - fs_phy_type | Dedicated | Dedicated | Dedicated | Shared ULPI | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | n/a | Dedicated | n/a | -| - num_dev_ep | 7 | 6 | 6 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 8 | 6 | 0 | -| - num_host_ch | 7 | 13 | 7 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 15 | 13 | 0 | -| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - mul_proc_intrpt | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | -| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - nptx_q_depth | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - ptx_q_depth | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | -| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| GHWCFG3 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | -| - xfer_size_width | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | -| - packet_size_width | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | -| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - i2c_enable | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | -| - vendor_ctrl_itf | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | -| - optional_feature_removed | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - synch_reset | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - otg_adp_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | -| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - battery_charger_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | -| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | -| - dfifo_depth | 4080 | 498 | 200 | 896 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 952 | 634 | 0 | -| GHWCFG4 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | -| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - partial_powerdown | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | -| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | -| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | -| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | -| - enhanced_lpm_support | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | -| - phy_data_width | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | -| - ctrl_ep_num | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - iddg_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - vbus_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | -| - a_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | -| - b_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | -| - session_end_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | -| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - num_dev_in_eps | 7 | 6 | 4 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 8 | 6 | 0 | -| - dma_desc_enable | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | -| - dma_desc_dynamic | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | +| | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5/H7RS HS | XMC4500 | GD32VF103 | +|:---------------------------|:----------------|:-------------|:--------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:------------------|:-------------|:------------| +| GUID | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00AEC000 | 0x00001000 | +| GSNPSID | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54292A | 0x00000000 | +| - specs version | 2.80a | 3.30a | 4.00a | 4.00a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 2.92a | 0.00W | +| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | +| GHWCFG2 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228F5930 | 0x00000000 | +| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | HNP SRP | HNP SRP | +| - arch | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | Slave only | +| - single_point | hub | hub | n/a | hub | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | n/a | hub | +| - hs_phy_type | UTMI+ | n/a | n/a | UTMI+/ULPI | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | n/a | n/a | +| - fs_phy_type | Dedicated | Dedicated | Dedicated | Shared ULPI | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | Dedicated | n/a | +| - num_dev_ep | 7 | 6 | 6 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | +| - num_host_ch | 7 | 13 | 7 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 13 | 0 | +| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - mul_proc_intrpt | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - nptx_q_depth | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - ptx_q_depth | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | +| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| GHWCFG3 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | +| - xfer_size_width | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | +| - packet_size_width | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | +| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - i2c_enable | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | +| - vendor_ctrl_itf | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | +| - optional_feature_removed | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - synch_reset | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - otg_adp_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - battery_charger_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | +| - dfifo_depth | 4080 | 498 | 200 | 896 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 634 | 0 | +| GHWCFG4 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | +| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - partial_powerdown | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - enhanced_lpm_support | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - phy_data_width | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8/16 bit | 8 bit | +| - ctrl_ep_num | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - iddg_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - vbus_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - a_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - b_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - session_end_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - num_dev_in_eps | 7 | 6 | 4 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | +| - dma_desc_enable | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | +| - dma_desc_dynamic | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py index 6ab4e0641..3d7d16dcc 100755 --- a/src/portable/synopsys/dwc2/dwc2_info.py +++ b/src/portable/synopsys/dwc2/dwc2_info.py @@ -21,8 +21,7 @@ dwc2_reg_value = { 'ST F76x HS': [0x2100, 0x4F54320A, 0, 0x229FE190, 0x03EED2E8, 0x23F00030], 'ST H743/H750': [0x2300, 0x4F54330A, 0, 0x229FE190, 0x03B8D2E8, 0xE3F00030], 'ST L476 FS': [0x2000, 0x4F54310A, 0, 0x229ED520, 0x0200D1E8, 0x17F08030], - 'ST U5A5 HS': [0x5000, 0x4F54411A, 0, 0x228FE052, 0x03B882E8, 0xE2103E30], - 'ST H7S3 HS': [0x5000, 0x4F54411A, 0, 0x228FE052, 0x03B882E8, 0xE2103E30], + 'ST U5A5/H7RS HS': [0x5000, 0x4F54411A, 0, 0x228FE052, 0x03B882E8, 0xE2103E30], 'XMC4500': [0xAEC000, 0x4F54292A, 0, 0x228F5930, 0x027A01E5, 0xDBF08030], 'GD32VF103': [0x1000, 0, 0, 0, 0, 0], } From 732a07ba5d48790b02e8b872cd5ec70f973a81c7 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 11 Jun 2025 19:59:24 +0700 Subject: [PATCH 213/382] fix linker issue with clang --- .../boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld index a81763bf9..3bd7f0b89 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld @@ -35,16 +35,12 @@ /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = ORIGIN(DTCM) + LENGTH(DTCM); /* end of "DTCM" Ram type memory */ - _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ __FLASH_BEGIN = 0x08000000; __FLASH_SIZE = 0x00010000; - __RAM_BEGIN = 0x24000000; __RAM_SIZE = 0x4FC00; __RAM_NONCACHEABLEBUFFER_SIZE = 0x4000; @@ -63,6 +59,9 @@ MEMORY FLASH (xrw) : ORIGIN = __FLASH_BEGIN, LENGTH = __FLASH_SIZE } +/* Highest address of the user mode stack */ +_estack = ORIGIN(DTCM) + LENGTH(DTCM); /* end of "DTCM" Ram type memory */ + /* Sections */ SECTIONS { @@ -100,14 +99,14 @@ SECTIONS . = ALIGN(4); } >FLASH - .ARM.extab (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + .ARM.extab : { . = ALIGN(4); *(.ARM.extab* .gnu.linkonce.armextab.*) . = ALIGN(4); } >FLASH - .ARM (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + .ARM : { . = ALIGN(4); __exidx_start = .; @@ -116,7 +115,7 @@ SECTIONS . = ALIGN(4); } >FLASH - .preinit_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + .preinit_array : { . = ALIGN(4); PROVIDE_HIDDEN (__preinit_array_start = .); @@ -125,7 +124,7 @@ SECTIONS . = ALIGN(4); } >FLASH - .init_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + .init_array : { . = ALIGN(4); PROVIDE_HIDDEN (__init_array_start = .); @@ -135,7 +134,7 @@ SECTIONS . = ALIGN(4); } >FLASH - .fini_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + .fini_array : { . = ALIGN(4); PROVIDE_HIDDEN (__fini_array_start = .); From edec37c1a31c1cb9e24f450299dacbd01afcb59a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jun 2025 14:07:51 +0700 Subject: [PATCH 214/382] fix cmake build --- .../boards/stm32n657nucleo/board.cmake | 10 ++---- .../stm32n6/boards/stm32n657nucleo/board.mk | 14 +++------ hw/bsp/stm32n6/family.cmake | 12 +++---- hw/bsp/stm32n6/family.mk | 31 ++++++------------- 4 files changed, 21 insertions(+), 46 deletions(-) diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake index 197b5108f..789eb9a2e 100644 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake @@ -1,17 +1,11 @@ set(MCU_VARIANT stm32n657xx) set(JLINK_DEVICE stm32n6xx) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/STM32N657XX_LRUN.ld) -set(LD_FILE_Clang ${LD_FILE_GNU}) - -set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/STM32N657XX_AXISRAM2_fsbl.ld) function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC - STM32N6xx - SEGGER_RTT_SECTION="noncacheable_buffer" - BUFFER_SIZE_UP=0x3000 + STM32N657xx ) target_sources(${TARGET} PUBLIC diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk index b851da0ca..bfbe5b23c 100644 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk @@ -1,23 +1,17 @@ -MCU_VARIANT = stm32n6xx -CFLAGS += -DSTM32N6xx - -# For flash-jlink target +MCU_VARIANT = stm32n657xx +CFLAGS += -DSTM32N657xx JLINK_DEVICE = stm32n6xx +LD_FILE_GCC = $(BOARD_PATH)/STM32N657XX_AXISRAM2_fsbl.ld + # flash target using on-board stlink flash: flash-stlink PORT = 1 - SRC_C += \ $(BOARD_PATH)/tcpp0203/tcpp0203.c \ $(BOARD_PATH)/tcpp0203/tcpp0203_reg.c \ INC += \ $(TOP)/$(BOARD_PATH)/tcpp0203 \ - -CFLAGS += \ - -DSEGGER_RTT_SECTION=\"noncacheable_buffer\" \ - -DSTM32N657xx - -DBUFFER_SIZE_UP=0x3000 \ diff --git a/hw/bsp/stm32n6/family.cmake b/hw/bsp/stm32n6/family.cmake index 600af7cdb..c2c634525 100644 --- a/hw/bsp/stm32n6/family.cmake +++ b/hw/bsp/stm32n6/family.cmake @@ -26,14 +26,12 @@ if (NOT DEFINED RHPORT_HOST) set(RHPORT_HOST 1) endif () -if (NOT DEFINED RHPORT_SPEED) - set(RHPORT_SPEED OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED) -endif () +# N6 are all high speed if (NOT DEFINED RHPORT_DEVICE_SPEED) - list(GET RHPORT_SPEED ${RHPORT_DEVICE} RHPORT_DEVICE_SPEED) + set(RHPORT_DEVICE_SPEED OPT_MODE_HIGH_SPEED) endif () if (NOT DEFINED RHPORT_HOST_SPEED) - list(GET RHPORT_SPEED ${RHPORT_HOST} RHPORT_HOST_SPEED) + set(RHPORT_HOST_SPEED OPT_MODE_HIGH_SPEED) endif () cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) @@ -61,7 +59,7 @@ function(add_board_target BOARD_TARGET) endif() add_library(${BOARD_TARGET} STATIC - ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}_ns.c + ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}_fsbl.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_dma.c @@ -86,6 +84,8 @@ function(add_board_target BOARD_TARGET) BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} BOARD_TUH_RHPORT=${RHPORT_HOST} BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} + SEGGER_RTT_SECTION="noncacheable_buffer" + BUFFER_SIZE_UP=0x3000 ) update_board(${BOARD_TARGET}) diff --git a/hw/bsp/stm32n6/family.mk b/hw/bsp/stm32n6/family.mk index 97930e189..d613e53d2 100644 --- a/hw/bsp/stm32n6/family.mk +++ b/hw/bsp/stm32n6/family.mk @@ -1,6 +1,5 @@ ST_FAMILY = n6 ST_PREFIX = stm32${ST_FAMILY}xx -ST_PREFIX_LONG = stm32${ST_FAMILY}57xx ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/${ST_PREFIX}_hal_driver @@ -12,26 +11,15 @@ CPU_CORE ?= cortex-m55 # ---------------------- # Port & Speed Selection # ---------------------- -RHPORT_SPEED ?= OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED RHPORT_DEVICE ?= 1 RHPORT_HOST ?= 1 -# Determine RHPORT_DEVICE_SPEED if not defined ifndef RHPORT_DEVICE_SPEED -ifeq ($(RHPORT_DEVICE), 0) - RHPORT_DEVICE_SPEED = $(firstword $(RHPORT_SPEED)) -else - RHPORT_DEVICE_SPEED = $(lastword $(RHPORT_SPEED)) -endif + RHPORT_DEVICE_SPEED = OPT_MODE_HIGH_SPEED endif -# Determine RHPORT_HOST_SPEED if not defined ifndef RHPORT_HOST_SPEED -ifeq ($(RHPORT_HOST), 0) - RHPORT_HOST_SPEED = $(firstword $(RHPORT_SPEED)) -else - RHPORT_HOST_SPEED = $(lastword $(RHPORT_SPEED)) -endif + RHPORT_HOST_SPEED = OPT_MODE_HIGH_SPEED endif # -------------- @@ -42,7 +30,9 @@ CFLAGS += \ -DBOARD_TUD_RHPORT=${RHPORT_DEVICE} \ -DBOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} \ -DBOARD_TUH_RHPORT=${RHPORT_HOST} \ - -DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} + -DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} \ + -DSEGGER_RTT_SECTION=\"noncacheable_buffer\" \ + -DBUFFER_SIZE_UP=0x3000 \ # GCC Flags CFLAGS_GCC += \ @@ -71,10 +61,10 @@ SRC_C += \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_dma.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_gpio.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_hcd.c \ - $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_i2c.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_i2c.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pcd.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pcd_ex.c \ - $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pwr.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pwr.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pwr_ex.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_rcc.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_rcc_ex.c \ @@ -89,13 +79,10 @@ INC += \ $(TOP)/$(ST_CMSIS)/Include \ $(TOP)/$(ST_HAL_DRIVER)/Inc -# Linker -LD_FILE_GCC = $(BOARD_PATH)/STM32N657XX_AXISRAM2_fsbl.ld - # Startup -SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_$(ST_PREFIX_LONG)_fsbl.s +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_$(MCU_VARIANT)_fsbl.s SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT).s # Linker -LD_FILE_GCC ?= $(ST_CMSIS)/Source/Templates/gcc/linker/$(ST_PREFIX_LONG)_flash.ld +LD_FILE_GCC ?= $(ST_CMSIS)/Source/Templates/gcc/linker/$(MCU_VARIANT)_flash.ld LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash.icf From 76b7468c746af5ad8496e9ed512366af249f972f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jun 2025 15:08:46 +0700 Subject: [PATCH 215/382] ci skip clang/iar build for stm32n6 add stm32-tcpp0203 driver as dependency for h7rs and n6 --- .github/workflows/ci_set_matrix.py | 3 +- .../boards/stm32h7s3nucleo/board.cmake | 11 +- .../stm32h7rs/boards/stm32h7s3nucleo/board.mk | 10 +- .../stm32h7s3nucleo/tcpp0203/LICENSE.txt | 6 - .../tcpp0203/Release_Notes.html | 205 -- .../tcpp0203/_htmresc/favicon.png | Bin 4126 -> 0 bytes .../tcpp0203/_htmresc/mini-st_2020.css | 1703 ----------------- .../tcpp0203/_htmresc/st_logo_2020.png | Bin 7520 -> 0 bytes .../stm32h7s3nucleo/tcpp0203/tcpp0203.c | 886 --------- .../stm32h7s3nucleo/tcpp0203/tcpp0203.h | 353 ---- .../stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c | 73 - .../stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h | 98 - hw/bsp/stm32h7rs/family.cmake | 3 + hw/bsp/stm32h7rs/family.mk | 3 + .../boards/stm32n657nucleo/board.cmake | 8 +- .../stm32n6/boards/stm32n657nucleo/board.mk | 6 +- .../stm32n657nucleo/tcpp0203/LICENSE.txt | 6 - .../tcpp0203/Release_Notes.html | 205 -- .../tcpp0203/_htmresc/favicon.png | Bin 4126 -> 0 bytes .../tcpp0203/_htmresc/mini-st_2020.css | 1703 ----------------- .../tcpp0203/_htmresc/st_logo_2020.png | Bin 7520 -> 0 bytes .../stm32n657nucleo/tcpp0203/tcpp0203.c | 886 --------- .../stm32n657nucleo/tcpp0203/tcpp0203.h | 353 ---- .../stm32n657nucleo/tcpp0203/tcpp0203_reg.c | 73 - .../stm32n657nucleo/tcpp0203/tcpp0203_reg.h | 98 - hw/bsp/stm32n6/family.cmake | 1 + hw/bsp/stm32n6/family.mk | 1 + tools/get_deps.py | 3 + 28 files changed, 25 insertions(+), 6672 deletions(-) delete mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt delete mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/Release_Notes.html delete mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/favicon.png delete mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css delete mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/st_logo_2020.png delete mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c delete mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h delete mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c delete mode 100644 hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h delete mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/LICENSE.txt delete mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/Release_Notes.html delete mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/favicon.png delete mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/mini-st_2020.css delete mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/st_logo_2020.png delete mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.c delete mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.h delete mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.c delete mode 100644 hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.h diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index 048c5f0ce..ddb3ee1fb 100755 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -41,7 +41,8 @@ family_list = { "stm32f7": ["arm-gcc", "arm-clang", "arm-iar"], "stm32g0 stm32g4 stm32h5": ["arm-gcc", "arm-clang", "arm-iar"], "stm32h7 stm32h7rs": ["arm-gcc", "arm-clang", "arm-iar"], - "stm32l0 stm32l4 stm32n6": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32l0 stm32l4": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32n6": ["arm-gcc"], "stm32u5 stm32wb": ["arm-gcc", "arm-clang", "arm-iar"], "xmc4000": ["arm-gcc"], "-bespressif_s2_devkitc": ["esp-idf"], diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake index ea9ffacf4..f52b70408 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake @@ -6,19 +6,14 @@ set(LD_FILE_Clang ${LD_FILE_GNU}) set(LD_FILE_IAR ${CMAKE_CURRENT_LIST_DIR}/stm32h7s3xx_flash.icf) function(update_board TARGET) - target_compile_definitions(${TARGET} PUBLIC STM32H7S3xx - SEGGER_RTT_SECTION="noncacheable_buffer" - BUFFER_SIZE_UP=0x3000 ) - target_sources(${TARGET} PUBLIC - # BSP - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tcpp0203/tcpp0203.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tcpp0203/tcpp0203_reg.c + ${ST_TCPP0203}/tcpp0203.c + ${ST_TCPP0203}/tcpp0203_reg.c ) target_include_directories(${TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tcpp0203 + ${ST_TCPP0203} ) endfunction() diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk index 1946f523c..cf0c2ff54 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk @@ -12,12 +12,8 @@ LD_FILE_GCC = $(BOARD_PATH)/stm32h7s3xx_flash.ld LD_FILE_IAR = $(BOARD_PATH)/stm32h7s3xx_flash.icf SRC_C += \ - $(BOARD_PATH)/tcpp0203/tcpp0203.c \ - $(BOARD_PATH)/tcpp0203/tcpp0203_reg.c \ + $(ST_TCPP0203)/tcpp0203.c \ + $(ST_TCPP0203)/tcpp0203_reg.c \ INC += \ - $(TOP)/$(BOARD_PATH)/tcpp0203 \ - -CFLAGS += \ - -DSEGGER_RTT_SECTION=\"noncacheable_buffer\" \ - -DBUFFER_SIZE_UP=0x3000 \ + $(TOP)/$(ST_TCPP0203) \ diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt deleted file mode 100644 index 1cbbc544a..000000000 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/LICENSE.txt +++ /dev/null @@ -1,6 +0,0 @@ -This software component is provided to you as part of a software package and -applicable license terms are in the Package_license file. If you received this -software component outside of a package or without applicable license terms, -the terms of the BSD-3-Clause license shall apply. -You may obtain a copy of the BSD-3-Clause at: -https://opensource.org/licenses/BSD-3-Clause diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/Release_Notes.html b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/Release_Notes.html deleted file mode 100644 index 6bbba86a4..000000000 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/Release_Notes.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - - Release Notes for TCPP0203 Component Driver - - - - - - -
-
-
-

Release Notes for TCPP0203 Component Driver

-

Copyright © 2020 STMicroelectronics
-

- -
-

Purpose

-

This driver provides a set of functions needed to drive TCPP0203 Type-C Port Protection component

-
-
-

Update History

-
- -
-

Main Changes

-

Maintenance release

-

Contents

- - - - - - - - - - - -
Headline
MISRA Rule-81.13 correction on TCPP0203 component driver files
-

Backward compatibility

-

No compatibility break with previous version

-

Dependencies

-
-
-
- -
-

Main Changes

-

Maintenance release

-

Contents

- - - - - - - - - - - - -
Fixed bugs list
Headline
MISRA corrections on TCPP0203 component driver files
-

Known Limitations

-

Outstanding bugs list : None

-

Requirements not met or planned in a forthcoming release : None

-

Development Toolchains and Compilers

-
    -
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • -
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • -
  • STM32CubeIDE toolchain V1.8.0
  • -
-

Backward compatibility

-

No compatibility break with previous version

-

Dependencies

-
-
-
- -
-

Main Changes

-

Maintenance release

-

Contents

- - - - - - - - - - - - -
Fixed bugs list
Headline
License updates
-

Known Limitations

-

Outstanding bugs list : None

-

Requirements not met or planned in a forthcoming release : None

-

Development Toolchains and Compilers

-
    -
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • -
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • -
  • STM32CubeIDE toolchain V1.6.0
  • -
-

Backward compatibility

-

No compatibility break with previous version

-

Dependencies

-
-
-
- -
-

Main Changes

-

Maintenance release

-

Contents

- - - - - - - - - - - - -
Fixed bugs list
Headline
CodeSpell correction on TCPP0203 component driver files
-

Known Limitations

-

Outstanding bugs list : None

-

Requirements not met or planned in a forthcoming release : None

-

Development Toolchains and Compilers

-
    -
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • -
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • -
  • STM32CubeIDE toolchain V1.5.0
  • -
-

Backward compatibility

-

No compatibility break with previous version

-

Dependencies

-
-
-
- -
-

Main Changes

-

Maintenance release

-

Contents

- - - - - - - - - - - - -
Fixed bugs list
Headline
MCUAstyle correction on TCPP0203 component driver files
-

Known Limitations

-

Outstanding bugs list : None

-

Requirements not met or planned in a forthcoming release : None

-

Development Toolchains and Compilers

-
    -
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • -
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • -
  • STM32CubeIDE toolchain V1.5.0
  • -
-

Backward compatibility

-

No compatibility break with previous version

-

Dependencies

-
-
-
- -
-

Main Changes

-
    -
  • First official release of TCPP0203 Type-C port Protection Component drivers
  • -
-
-
-
-
-
-

For complete documentation on STM32,visit: [www.st.com/stm32]

-This release note uses up to date web standards and, for this reason, should not be opened with Internet Explorer but preferably with popular browsers such as Google Chrome, Mozilla Firefox, Opera or Microsoft Edge. -
- - diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/favicon.png b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/favicon.png deleted file mode 100644 index 06713eec4974e141c6e9b4156d34e61e89f282ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4126 zcmV+(5aI8MP)ZIGU@QfPy~$kHP}Vz9c$a)g>fT6hB^OaK4>c|MGS0000HbW%=J|NsC0|NsC0 z|NsC0|NsC0041%NVgLXD!bwCyRCwCllie1CAP9sJ&9ooo{hxLjw5@YC+xxf~%TE}{ zNd5%935b--eKa7{Q8)vZ;eI6pGFH>rL)887WOA={e(b_&0g-g6to#Hm2B3vqWV>1u z@z7*I(bdWdx-Y=OT@|og)oZEgAbc7ep|Gf{$7j1Oa#T&r4>0xv(+}tR_4biWa z1Q-BfcsgeLIJPbT0000rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000F^NklQWRUVq~pvFslpiNq83Yr*1(ELa!!kppKfxQKEkPzz^I>0W)!71xam z(B64`)5a~kHf9SBOp*Wvo{xA*e4|Kv3g6TCo+fF8q^C$|g>#NlXyY$%lmkmCh$x1Z zFbJ_hiDG`37w>KPVB83d7E3>R@-M9$`|}|QFF}1qSk!nanPdVd3K38edo3y+D*=Uo zfOWCwj(F@GSjPG&B<0O;H!Zm0g>eDeK09{b@xB};mEy; z;Gp5H_Cr65qKM1uYIu6x&16!Ei=BHfJLe)1IUnFqc6d#D=ZVQmV9C73vy1=x$SK;s z=*CYZP+Ei1D5Vjl#u88v5dv#jId?iu)8mM}{mD`GcMXtAC5ap?ZoKr&iYuqTKHe$t zTR%R$ZZwxec?l+0r_LIVbe-mzH+D0*ZYsu4BE~~JA2A+AD?BAArO=g8ZfvXtU~o9c zZ(Bd-RFK5jh*DvM1v6^41HB@0K0qn7E8E&Xz1mk6hvmx?*|WB_H!dcO;5R$=<4b~s z5zr3N4zxlkMKOrDeny(PGpEM6^hGyc7lhg>MWtM!af*pn%&q_PxI(n^(-Zd{ICPAp z(WE@Zz5|EZyt{MEDy&l5$Cba^zU!9k&;Vs7lk$@o02LOwb#e2{#3%Cn2>kQF(RKUU z+tW!;FT0@d+TX^L;>@3RytlTP&ts$pqA}TwENBlg9?$-D zF9Sn4URZx8)hVBw<~NY=h3=so7{jEhG%Zc_0QBSvY~K4BS|W5MAem5XSb6m}VDN$f zy+b3n9qjIJoHM5pqYa`IPH9AIoM=!AE1Er>r|3E}#Jq-S)cTrfD&TZjAuN@+V}3mi zlhOce+q<8>Y?i93G=*Z3Web`ri!Q%p%LR*(bB?;|)B`&=J&ab0Z(UKpbzyZV5o*#& z0FLzzaI$v*-#WB)+`n>BoJ*1AwU0XSu;@w&Hu1WYXVR#!8itC%68CzMeiXhL#`9W$9J30NB-Wg!ex`hBlg9F5u@&o4>hd`TWPv z{r{JbyvQGZzbyvPS}zAifbhF49z~X|@9v|!=No>qsF|P~vf=g>7#%0yk<U?Ha8*Z4HW>#8w>z$A3 z>^uQlk;$a-6CQ(uc@RM)Cbss!xuPVl2@c1u-5tEUw}U8OfP_J+QYhfu$B<0Cj3xm7 c?*aZZ00ulYFs-m=@&Et;07*qoM6N<$f~=14i~s-t diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css deleted file mode 100644 index dd19969d1..000000000 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/mini-st_2020.css +++ /dev/null @@ -1,1703 +0,0 @@ -@charset "UTF-8"; -/* - Flavor name: Custom (mini-custom) - Generated online - https://minicss.org/flavors - mini.css version: v3.0.1 -*/ -/* - Browsers resets and base typography. -*/ -/* Core module CSS variable definitions */ -:root { - --fore-color: #03234b; - --secondary-fore-color: #03234b; - --back-color: #ffffff; - --secondary-back-color: #ffffff; - --blockquote-color: #e6007e; - --pre-color: #e6007e; - --border-color: #3cb4e6; - --secondary-border-color: #3cb4e6; - --heading-ratio: 1.2; - --universal-margin: 0.5rem; - --universal-padding: 0.25rem; - --universal-border-radius: 0.075rem; - --background-margin: 1.5%; - --a-link-color: #3cb4e6; - --a-visited-color: #8c0078; } - -html { - font-size: 13.5px; } - -a, b, del, em, i, ins, q, span, strong, u { - font-size: 1em; } - -html, * { - font-family: -apple-system, BlinkMacSystemFont, Helvetica, arial, sans-serif; - line-height: 1.25; - -webkit-text-size-adjust: 100%; } - -* { - font-size: 1rem; } - -body { - margin: 0; - color: var(--fore-color); - @background: var(--back-color); - background: var(--back-color) linear-gradient(#ffd200, #ffd200) repeat-y left top; - background-size: var(--background-margin); - } - -details { - display: block; } - -summary { - display: list-item; } - -abbr[title] { - border-bottom: none; - text-decoration: underline dotted; } - -input { - overflow: visible; } - -img { - max-width: 100%; - height: auto; } - -h1, h2, h3, h4, h5, h6 { - line-height: 1.25; - margin: calc(1.5 * var(--universal-margin)) var(--universal-margin); - font-weight: 400; } - h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { - color: var(--secondary-fore-color); - display: block; - margin-top: -0.25rem; } - -h1 { - font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio)); } - -h2 { - font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) ); - border-style: none none solid none ; - border-width: thin; - border-color: var(--border-color); } -h3 { - font-size: calc(1rem * var(--heading-ratio) ); } - -h4 { - font-size: calc(1rem * var(--heading-ratio)); } - -h5 { - font-size: 1rem; } - -h6 { - font-size: calc(1rem / var(--heading-ratio)); } - -p { - margin: var(--universal-margin); } - -ol, ul { - margin: var(--universal-margin); - padding-left: calc(3 * var(--universal-margin)); } - -b, strong { - font-weight: 700; } - -hr { - box-sizing: content-box; - border: 0; - line-height: 1.25em; - margin: var(--universal-margin); - height: 0.0714285714rem; - background: linear-gradient(to right, transparent, var(--border-color) 20%, var(--border-color) 80%, transparent); } - -blockquote { - display: block; - position: relative; - font-style: italic; - color: var(--secondary-fore-color); - margin: var(--universal-margin); - padding: calc(3 * var(--universal-padding)); - border: 0.0714285714rem solid var(--secondary-border-color); - border-left: 0.3rem solid var(--blockquote-color); - border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } - blockquote:before { - position: absolute; - top: calc(0rem - var(--universal-padding)); - left: 0; - font-family: sans-serif; - font-size: 2rem; - font-weight: 800; - content: "\201c"; - color: var(--blockquote-color); } - blockquote[cite]:after { - font-style: normal; - font-size: 0.75em; - font-weight: 700; - content: "\a— " attr(cite); - white-space: pre; } - -code, kbd, pre, samp { - font-family: Menlo, Consolas, monospace; - font-size: 0.85em; } - -code { - background: var(--secondary-back-color); - border-radius: var(--universal-border-radius); - padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } - -kbd { - background: var(--fore-color); - color: var(--back-color); - border-radius: var(--universal-border-radius); - padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } - -pre { - overflow: auto; - background: var(--secondary-back-color); - padding: calc(1.5 * var(--universal-padding)); - margin: var(--universal-margin); - border: 0.0714285714rem solid var(--secondary-border-color); - border-left: 0.2857142857rem solid var(--pre-color); - border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } - -sup, sub, code, kbd { - line-height: 0; - position: relative; - vertical-align: baseline; } - -small, sup, sub, figcaption { - font-size: 0.75em; } - -sup { - top: -0.5em; } - -sub { - bottom: -0.25em; } - -figure { - margin: var(--universal-margin); } - -figcaption { - color: var(--secondary-fore-color); } - -a { - text-decoration: none; } - a:link { - color: var(--a-link-color); } - a:visited { - color: var(--a-visited-color); } - a:hover, a:focus { - text-decoration: underline; } - -/* - Definitions for the grid system, cards and containers. -*/ -.container { - margin: 0 auto; - padding: 0 calc(1.5 * var(--universal-padding)); } - -.row { - box-sizing: border-box; - display: flex; - flex: 0 1 auto; - flex-flow: row wrap; - margin: 0 0 0 var(--background-margin); } - -.col-sm, -[class^='col-sm-'], -[class^='col-sm-offset-'], -.row[class*='cols-sm-'] > * { - box-sizing: border-box; - flex: 0 0 auto; - padding: 0 calc(var(--universal-padding) / 2); } - -.col-sm, -.row.cols-sm > * { - max-width: 100%; - flex-grow: 1; - flex-basis: 0; } - -.col-sm-1, -.row.cols-sm-1 > * { - max-width: 8.3333333333%; - flex-basis: 8.3333333333%; } - -.col-sm-offset-0 { - margin-left: 0; } - -.col-sm-2, -.row.cols-sm-2 > * { - max-width: 16.6666666667%; - flex-basis: 16.6666666667%; } - -.col-sm-offset-1 { - margin-left: 8.3333333333%; } - -.col-sm-3, -.row.cols-sm-3 > * { - max-width: 25%; - flex-basis: 25%; } - -.col-sm-offset-2 { - margin-left: 16.6666666667%; } - -.col-sm-4, -.row.cols-sm-4 > * { - max-width: 33.3333333333%; - flex-basis: 33.3333333333%; } - -.col-sm-offset-3 { - margin-left: 25%; } - -.col-sm-5, -.row.cols-sm-5 > * { - max-width: 41.6666666667%; - flex-basis: 41.6666666667%; } - -.col-sm-offset-4 { - margin-left: 33.3333333333%; } - -.col-sm-6, -.row.cols-sm-6 > * { - max-width: 50%; - flex-basis: 50%; } - -.col-sm-offset-5 { - margin-left: 41.6666666667%; } - -.col-sm-7, -.row.cols-sm-7 > * { - max-width: 58.3333333333%; - flex-basis: 58.3333333333%; } - -.col-sm-offset-6 { - margin-left: 50%; } - -.col-sm-8, -.row.cols-sm-8 > * { - max-width: 66.6666666667%; - flex-basis: 66.6666666667%; } - -.col-sm-offset-7 { - margin-left: 58.3333333333%; } - -.col-sm-9, -.row.cols-sm-9 > * { - max-width: 75%; - flex-basis: 75%; } - -.col-sm-offset-8 { - margin-left: 66.6666666667%; } - -.col-sm-10, -.row.cols-sm-10 > * { - max-width: 83.3333333333%; - flex-basis: 83.3333333333%; } - -.col-sm-offset-9 { - margin-left: 75%; } - -.col-sm-11, -.row.cols-sm-11 > * { - max-width: 91.6666666667%; - flex-basis: 91.6666666667%; } - -.col-sm-offset-10 { - margin-left: 83.3333333333%; } - -.col-sm-12, -.row.cols-sm-12 > * { - max-width: 100%; - flex-basis: 100%; } - -.col-sm-offset-11 { - margin-left: 91.6666666667%; } - -.col-sm-normal { - order: initial; } - -.col-sm-first { - order: -999; } - -.col-sm-last { - order: 999; } - -@media screen and (min-width: 500px) { - .col-md, - [class^='col-md-'], - [class^='col-md-offset-'], - .row[class*='cols-md-'] > * { - box-sizing: border-box; - flex: 0 0 auto; - padding: 0 calc(var(--universal-padding) / 2); } - - .col-md, - .row.cols-md > * { - max-width: 100%; - flex-grow: 1; - flex-basis: 0; } - - .col-md-1, - .row.cols-md-1 > * { - max-width: 8.3333333333%; - flex-basis: 8.3333333333%; } - - .col-md-offset-0 { - margin-left: 0; } - - .col-md-2, - .row.cols-md-2 > * { - max-width: 16.6666666667%; - flex-basis: 16.6666666667%; } - - .col-md-offset-1 { - margin-left: 8.3333333333%; } - - .col-md-3, - .row.cols-md-3 > * { - max-width: 25%; - flex-basis: 25%; } - - .col-md-offset-2 { - margin-left: 16.6666666667%; } - - .col-md-4, - .row.cols-md-4 > * { - max-width: 33.3333333333%; - flex-basis: 33.3333333333%; } - - .col-md-offset-3 { - margin-left: 25%; } - - .col-md-5, - .row.cols-md-5 > * { - max-width: 41.6666666667%; - flex-basis: 41.6666666667%; } - - .col-md-offset-4 { - margin-left: 33.3333333333%; } - - .col-md-6, - .row.cols-md-6 > * { - max-width: 50%; - flex-basis: 50%; } - - .col-md-offset-5 { - margin-left: 41.6666666667%; } - - .col-md-7, - .row.cols-md-7 > * { - max-width: 58.3333333333%; - flex-basis: 58.3333333333%; } - - .col-md-offset-6 { - margin-left: 50%; } - - .col-md-8, - .row.cols-md-8 > * { - max-width: 66.6666666667%; - flex-basis: 66.6666666667%; } - - .col-md-offset-7 { - margin-left: 58.3333333333%; } - - .col-md-9, - .row.cols-md-9 > * { - max-width: 75%; - flex-basis: 75%; } - - .col-md-offset-8 { - margin-left: 66.6666666667%; } - - .col-md-10, - .row.cols-md-10 > * { - max-width: 83.3333333333%; - flex-basis: 83.3333333333%; } - - .col-md-offset-9 { - margin-left: 75%; } - - .col-md-11, - .row.cols-md-11 > * { - max-width: 91.6666666667%; - flex-basis: 91.6666666667%; } - - .col-md-offset-10 { - margin-left: 83.3333333333%; } - - .col-md-12, - .row.cols-md-12 > * { - max-width: 100%; - flex-basis: 100%; } - - .col-md-offset-11 { - margin-left: 91.6666666667%; } - - .col-md-normal { - order: initial; } - - .col-md-first { - order: -999; } - - .col-md-last { - order: 999; } } -@media screen and (min-width: 1280px) { - .col-lg, - [class^='col-lg-'], - [class^='col-lg-offset-'], - .row[class*='cols-lg-'] > * { - box-sizing: border-box; - flex: 0 0 auto; - padding: 0 calc(var(--universal-padding) / 2); } - - .col-lg, - .row.cols-lg > * { - max-width: 100%; - flex-grow: 1; - flex-basis: 0; } - - .col-lg-1, - .row.cols-lg-1 > * { - max-width: 8.3333333333%; - flex-basis: 8.3333333333%; } - - .col-lg-offset-0 { - margin-left: 0; } - - .col-lg-2, - .row.cols-lg-2 > * { - max-width: 16.6666666667%; - flex-basis: 16.6666666667%; } - - .col-lg-offset-1 { - margin-left: 8.3333333333%; } - - .col-lg-3, - .row.cols-lg-3 > * { - max-width: 25%; - flex-basis: 25%; } - - .col-lg-offset-2 { - margin-left: 16.6666666667%; } - - .col-lg-4, - .row.cols-lg-4 > * { - max-width: 33.3333333333%; - flex-basis: 33.3333333333%; } - - .col-lg-offset-3 { - margin-left: 25%; } - - .col-lg-5, - .row.cols-lg-5 > * { - max-width: 41.6666666667%; - flex-basis: 41.6666666667%; } - - .col-lg-offset-4 { - margin-left: 33.3333333333%; } - - .col-lg-6, - .row.cols-lg-6 > * { - max-width: 50%; - flex-basis: 50%; } - - .col-lg-offset-5 { - margin-left: 41.6666666667%; } - - .col-lg-7, - .row.cols-lg-7 > * { - max-width: 58.3333333333%; - flex-basis: 58.3333333333%; } - - .col-lg-offset-6 { - margin-left: 50%; } - - .col-lg-8, - .row.cols-lg-8 > * { - max-width: 66.6666666667%; - flex-basis: 66.6666666667%; } - - .col-lg-offset-7 { - margin-left: 58.3333333333%; } - - .col-lg-9, - .row.cols-lg-9 > * { - max-width: 75%; - flex-basis: 75%; } - - .col-lg-offset-8 { - margin-left: 66.6666666667%; } - - .col-lg-10, - .row.cols-lg-10 > * { - max-width: 83.3333333333%; - flex-basis: 83.3333333333%; } - - .col-lg-offset-9 { - margin-left: 75%; } - - .col-lg-11, - .row.cols-lg-11 > * { - max-width: 91.6666666667%; - flex-basis: 91.6666666667%; } - - .col-lg-offset-10 { - margin-left: 83.3333333333%; } - - .col-lg-12, - .row.cols-lg-12 > * { - max-width: 100%; - flex-basis: 100%; } - - .col-lg-offset-11 { - margin-left: 91.6666666667%; } - - .col-lg-normal { - order: initial; } - - .col-lg-first { - order: -999; } - - .col-lg-last { - order: 999; } } -/* Card component CSS variable definitions */ -:root { - --card-back-color: #3cb4e6; - --card-fore-color: #03234b; - --card-border-color: #03234b; } - -.card { - display: flex; - flex-direction: column; - justify-content: space-between; - align-self: center; - position: relative; - width: 100%; - background: var(--card-back-color); - color: var(--card-fore-color); - border: 0.0714285714rem solid var(--card-border-color); - border-radius: var(--universal-border-radius); - margin: var(--universal-margin); - overflow: hidden; } - @media screen and (min-width: 320px) { - .card { - max-width: 320px; } } - .card > .sectione { - background: var(--card-back-color); - color: var(--card-fore-color); - box-sizing: border-box; - margin: 0; - border: 0; - border-radius: 0; - border-bottom: 0.0714285714rem solid var(--card-border-color); - padding: var(--universal-padding); - width: 100%; } - .card > .sectione.media { - height: 200px; - padding: 0; - -o-object-fit: cover; - object-fit: cover; } - .card > .sectione:last-child { - border-bottom: 0; } - -/* - Custom elements for card elements. -*/ -@media screen and (min-width: 240px) { - .card.small { - max-width: 240px; } } -@media screen and (min-width: 480px) { - .card.large { - max-width: 480px; } } -.card.fluid { - max-width: 100%; - width: auto; } - -.card.warning { - --card-back-color: #e5b8b7; - --card-fore-color: #3b234b; - --card-border-color: #8c0078; } - -.card.error { - --card-back-color: #464650; - --card-fore-color: #ffffff; - --card-border-color: #8c0078; } - -.card > .sectione.dark { - --card-back-color: #3b234b; - --card-fore-color: #ffffff; } - -.card > .sectione.double-padded { - padding: calc(1.5 * var(--universal-padding)); } - -/* - Definitions for forms and input elements. -*/ -/* Input_control module CSS variable definitions */ -:root { - --form-back-color: #ffe97f; - --form-fore-color: #03234b; - --form-border-color: #3cb4e6; - --input-back-color: #ffffff; - --input-fore-color: #03234b; - --input-border-color: #3cb4e6; - --input-focus-color: #0288d1; - --input-invalid-color: #d32f2f; - --button-back-color: #e2e2e2; - --button-hover-back-color: #dcdcdc; - --button-fore-color: #212121; - --button-border-color: transparent; - --button-hover-border-color: transparent; - --button-group-border-color: rgba(124, 124, 124, 0.54); } - -form { - background: var(--form-back-color); - color: var(--form-fore-color); - border: 0.0714285714rem solid var(--form-border-color); - border-radius: var(--universal-border-radius); - margin: var(--universal-margin); - padding: calc(2 * var(--universal-padding)) var(--universal-padding); } - -fieldset { - border: 0.0714285714rem solid var(--form-border-color); - border-radius: var(--universal-border-radius); - margin: calc(var(--universal-margin) / 4); - padding: var(--universal-padding); } - -legend { - box-sizing: border-box; - display: table; - max-width: 100%; - white-space: normal; - font-weight: 500; - padding: calc(var(--universal-padding) / 2); } - -label { - padding: calc(var(--universal-padding) / 2) var(--universal-padding); } - -.input-group { - display: inline-block; } - .input-group.fluid { - display: flex; - align-items: center; - justify-content: center; } - .input-group.fluid > input { - max-width: 100%; - flex-grow: 1; - flex-basis: 0px; } - @media screen and (max-width: 499px) { - .input-group.fluid { - align-items: stretch; - flex-direction: column; } } - .input-group.vertical { - display: flex; - align-items: stretch; - flex-direction: column; } - .input-group.vertical > input { - max-width: 100%; - flex-grow: 1; - flex-basis: 0px; } - -[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { - height: auto; } - -[type="search"] { - -webkit-appearance: textfield; - outline-offset: -2px; } - -[type="search"]::-webkit-search-cancel-button, -[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; } - -input:not([type]), [type="text"], [type="email"], [type="number"], [type="search"], -[type="password"], [type="url"], [type="tel"], [type="checkbox"], [type="radio"], textarea, select { - box-sizing: border-box; - background: var(--input-back-color); - color: var(--input-fore-color); - border: 0.0714285714rem solid var(--input-border-color); - border-radius: var(--universal-border-radius); - margin: calc(var(--universal-margin) / 2); - padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } - -input:not([type="button"]):not([type="submit"]):not([type="reset"]):hover, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus, textarea:hover, textarea:focus, select:hover, select:focus { - border-color: var(--input-focus-color); - box-shadow: none; } -input:not([type="button"]):not([type="submit"]):not([type="reset"]):invalid, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus:invalid, textarea:invalid, textarea:focus:invalid, select:invalid, select:focus:invalid { - border-color: var(--input-invalid-color); - box-shadow: none; } -input:not([type="button"]):not([type="submit"]):not([type="reset"])[readonly], textarea[readonly], select[readonly] { - background: var(--secondary-back-color); } - -select { - max-width: 100%; } - -option { - overflow: hidden; - text-overflow: ellipsis; } - -[type="checkbox"], [type="radio"] { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - position: relative; - height: calc(1rem + var(--universal-padding) / 2); - width: calc(1rem + var(--universal-padding) / 2); - vertical-align: text-bottom; - padding: 0; - flex-basis: calc(1rem + var(--universal-padding) / 2) !important; - flex-grow: 0 !important; } - [type="checkbox"]:checked:before, [type="radio"]:checked:before { - position: absolute; } - -[type="checkbox"]:checked:before { - content: '\2713'; - font-family: sans-serif; - font-size: calc(1rem + var(--universal-padding) / 2); - top: calc(0rem - var(--universal-padding)); - left: calc(var(--universal-padding) / 4); } - -[type="radio"] { - border-radius: 100%; } - [type="radio"]:checked:before { - border-radius: 100%; - content: ''; - top: calc(0.0714285714rem + var(--universal-padding) / 2); - left: calc(0.0714285714rem + var(--universal-padding) / 2); - background: var(--input-fore-color); - width: 0.5rem; - height: 0.5rem; } - -:placeholder-shown { - color: var(--input-fore-color); } - -::-ms-placeholder { - color: var(--input-fore-color); - opacity: 0.54; } - -button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { - border-style: none; - padding: 0; } - -button, html [type="button"], [type="reset"], [type="submit"] { - -webkit-appearance: button; } - -button { - overflow: visible; - text-transform: none; } - -button, [type="button"], [type="submit"], [type="reset"], -a.button, label.button, .button, -a[role="button"], label[role="button"], [role="button"] { - display: inline-block; - background: var(--button-back-color); - color: var(--button-fore-color); - border: 0.0714285714rem solid var(--button-border-color); - border-radius: var(--universal-border-radius); - padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); - margin: var(--universal-margin); - text-decoration: none; - cursor: pointer; - transition: background 0.3s; } - button:hover, button:focus, [type="button"]:hover, [type="button"]:focus, [type="submit"]:hover, [type="submit"]:focus, [type="reset"]:hover, [type="reset"]:focus, - a.button:hover, - a.button:focus, label.button:hover, label.button:focus, .button:hover, .button:focus, - a[role="button"]:hover, - a[role="button"]:focus, label[role="button"]:hover, label[role="button"]:focus, [role="button"]:hover, [role="button"]:focus { - background: var(--button-hover-back-color); - border-color: var(--button-hover-border-color); } - -input:disabled, input[disabled], textarea:disabled, textarea[disabled], select:disabled, select[disabled], button:disabled, button[disabled], .button:disabled, .button[disabled], [role="button"]:disabled, [role="button"][disabled] { - cursor: not-allowed; - opacity: 0.75; } - -.button-group { - display: flex; - border: 0.0714285714rem solid var(--button-group-border-color); - border-radius: var(--universal-border-radius); - margin: var(--universal-margin); } - .button-group > button, .button-group [type="button"], .button-group > [type="submit"], .button-group > [type="reset"], .button-group > .button, .button-group > [role="button"] { - margin: 0; - max-width: 100%; - flex: 1 1 auto; - text-align: center; - border: 0; - border-radius: 0; - box-shadow: none; } - .button-group > :not(:first-child) { - border-left: 0.0714285714rem solid var(--button-group-border-color); } - @media screen and (max-width: 499px) { - .button-group { - flex-direction: column; } - .button-group > :not(:first-child) { - border: 0; - border-top: 0.0714285714rem solid var(--button-group-border-color); } } - -/* - Custom elements for forms and input elements. -*/ -button.primary, [type="button"].primary, [type="submit"].primary, [type="reset"].primary, .button.primary, [role="button"].primary { - --button-back-color: #1976d2; - --button-fore-color: #f8f8f8; } - button.primary:hover, button.primary:focus, [type="button"].primary:hover, [type="button"].primary:focus, [type="submit"].primary:hover, [type="submit"].primary:focus, [type="reset"].primary:hover, [type="reset"].primary:focus, .button.primary:hover, .button.primary:focus, [role="button"].primary:hover, [role="button"].primary:focus { - --button-hover-back-color: #1565c0; } - -button.secondary, [type="button"].secondary, [type="submit"].secondary, [type="reset"].secondary, .button.secondary, [role="button"].secondary { - --button-back-color: #d32f2f; - --button-fore-color: #f8f8f8; } - button.secondary:hover, button.secondary:focus, [type="button"].secondary:hover, [type="button"].secondary:focus, [type="submit"].secondary:hover, [type="submit"].secondary:focus, [type="reset"].secondary:hover, [type="reset"].secondary:focus, .button.secondary:hover, .button.secondary:focus, [role="button"].secondary:hover, [role="button"].secondary:focus { - --button-hover-back-color: #c62828; } - -button.tertiary, [type="button"].tertiary, [type="submit"].tertiary, [type="reset"].tertiary, .button.tertiary, [role="button"].tertiary { - --button-back-color: #308732; - --button-fore-color: #f8f8f8; } - button.tertiary:hover, button.tertiary:focus, [type="button"].tertiary:hover, [type="button"].tertiary:focus, [type="submit"].tertiary:hover, [type="submit"].tertiary:focus, [type="reset"].tertiary:hover, [type="reset"].tertiary:focus, .button.tertiary:hover, .button.tertiary:focus, [role="button"].tertiary:hover, [role="button"].tertiary:focus { - --button-hover-back-color: #277529; } - -button.inverse, [type="button"].inverse, [type="submit"].inverse, [type="reset"].inverse, .button.inverse, [role="button"].inverse { - --button-back-color: #212121; - --button-fore-color: #f8f8f8; } - button.inverse:hover, button.inverse:focus, [type="button"].inverse:hover, [type="button"].inverse:focus, [type="submit"].inverse:hover, [type="submit"].inverse:focus, [type="reset"].inverse:hover, [type="reset"].inverse:focus, .button.inverse:hover, .button.inverse:focus, [role="button"].inverse:hover, [role="button"].inverse:focus { - --button-hover-back-color: #111; } - -button.small, [type="button"].small, [type="submit"].small, [type="reset"].small, .button.small, [role="button"].small { - padding: calc(0.5 * var(--universal-padding)) calc(0.75 * var(--universal-padding)); - margin: var(--universal-margin); } - -button.large, [type="button"].large, [type="submit"].large, [type="reset"].large, .button.large, [role="button"].large { - padding: calc(1.5 * var(--universal-padding)) calc(2 * var(--universal-padding)); - margin: var(--universal-margin); } - -/* - Definitions for navigation elements. -*/ -/* Navigation module CSS variable definitions */ -:root { - --header-back-color: #03234b; - --header-hover-back-color: #ffd200; - --header-fore-color: #ffffff; - --header-border-color: #3cb4e6; - --nav-back-color: #ffffff; - --nav-hover-back-color: #ffe97f; - --nav-fore-color: #e6007e; - --nav-border-color: #3cb4e6; - --nav-link-color: #3cb4e6; - --footer-fore-color: #ffffff; - --footer-back-color: #03234b; - --footer-border-color: #3cb4e6; - --footer-link-color: #3cb4e6; - --drawer-back-color: #ffffff; - --drawer-hover-back-color: #ffe97f; - --drawer-border-color: #3cb4e6; - --drawer-close-color: #e6007e; } - -header { - height: 2.75rem; - background: var(--header-back-color); - color: var(--header-fore-color); - border-bottom: 0.0714285714rem solid var(--header-border-color); - padding: calc(var(--universal-padding) / 4) 0; - white-space: nowrap; - overflow-x: auto; - overflow-y: hidden; } - header.row { - box-sizing: content-box; } - header .logo { - color: var(--header-fore-color); - font-size: 1.75rem; - padding: var(--universal-padding) calc(2 * var(--universal-padding)); - text-decoration: none; } - header button, header [type="button"], header .button, header [role="button"] { - box-sizing: border-box; - position: relative; - top: calc(0rem - var(--universal-padding) / 4); - height: calc(3.1875rem + var(--universal-padding) / 2); - background: var(--header-back-color); - line-height: calc(3.1875rem - var(--universal-padding) * 1.5); - text-align: center; - color: var(--header-fore-color); - border: 0; - border-radius: 0; - margin: 0; - text-transform: uppercase; } - header button:hover, header button:focus, header [type="button"]:hover, header [type="button"]:focus, header .button:hover, header .button:focus, header [role="button"]:hover, header [role="button"]:focus { - background: var(--header-hover-back-color); } - -nav { - background: var(--nav-back-color); - color: var(--nav-fore-color); - border: 0.0714285714rem solid var(--nav-border-color); - border-radius: var(--universal-border-radius); - margin: var(--universal-margin); } - nav * { - padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } - nav a, nav a:visited { - display: block; - color: var(--nav-link-color); - border-radius: var(--universal-border-radius); - transition: background 0.3s; } - nav a:hover, nav a:focus, nav a:visited:hover, nav a:visited:focus { - text-decoration: none; - background: var(--nav-hover-back-color); } - nav .sublink-1 { - position: relative; - margin-left: calc(2 * var(--universal-padding)); } - nav .sublink-1:before { - position: absolute; - left: calc(var(--universal-padding) - 1 * var(--universal-padding)); - top: -0.0714285714rem; - content: ''; - height: 100%; - border: 0.0714285714rem solid var(--nav-border-color); - border-left: 0; } - nav .sublink-2 { - position: relative; - margin-left: calc(4 * var(--universal-padding)); } - nav .sublink-2:before { - position: absolute; - left: calc(var(--universal-padding) - 3 * var(--universal-padding)); - top: -0.0714285714rem; - content: ''; - height: 100%; - border: 0.0714285714rem solid var(--nav-border-color); - border-left: 0; } - -footer { - background: var(--footer-back-color); - color: var(--footer-fore-color); - border-top: 0.0714285714rem solid var(--footer-border-color); - padding: calc(2 * var(--universal-padding)) var(--universal-padding); - font-size: 0.875rem; } - footer a, footer a:visited { - color: var(--footer-link-color); } - -header.sticky { - position: -webkit-sticky; - position: sticky; - z-index: 1101; - top: 0; } - -footer.sticky { - position: -webkit-sticky; - position: sticky; - z-index: 1101; - bottom: 0; } - -.drawer-toggle:before { - display: inline-block; - position: relative; - vertical-align: bottom; - content: '\00a0\2261\00a0'; - font-family: sans-serif; - font-size: 1.5em; } -@media screen and (min-width: 500px) { - .drawer-toggle:not(.persistent) { - display: none; } } - -[type="checkbox"].drawer { - height: 1px; - width: 1px; - margin: -1px; - overflow: hidden; - position: absolute; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); } - [type="checkbox"].drawer + * { - display: block; - box-sizing: border-box; - position: fixed; - top: 0; - width: 320px; - height: 100vh; - overflow-y: auto; - background: var(--drawer-back-color); - border: 0.0714285714rem solid var(--drawer-border-color); - border-radius: 0; - margin: 0; - z-index: 1110; - right: -320px; - transition: right 0.3s; } - [type="checkbox"].drawer + * .drawer-close { - position: absolute; - top: var(--universal-margin); - right: var(--universal-margin); - z-index: 1111; - width: 2rem; - height: 2rem; - border-radius: var(--universal-border-radius); - padding: var(--universal-padding); - margin: 0; - cursor: pointer; - transition: background 0.3s; } - [type="checkbox"].drawer + * .drawer-close:before { - display: block; - content: '\00D7'; - color: var(--drawer-close-color); - position: relative; - font-family: sans-serif; - font-size: 2rem; - line-height: 1; - text-align: center; } - [type="checkbox"].drawer + * .drawer-close:hover, [type="checkbox"].drawer + * .drawer-close:focus { - background: var(--drawer-hover-back-color); } - @media screen and (max-width: 320px) { - [type="checkbox"].drawer + * { - width: 100%; } } - [type="checkbox"].drawer:checked + * { - right: 0; } - @media screen and (min-width: 500px) { - [type="checkbox"].drawer:not(.persistent) + * { - position: static; - height: 100%; - z-index: 1100; } - [type="checkbox"].drawer:not(.persistent) + * .drawer-close { - display: none; } } - -/* - Definitions for the responsive table component. -*/ -/* Table module CSS variable definitions. */ -:root { - --table-border-color: #03234b; - --table-border-separator-color: #03234b; - --table-head-back-color: #03234b; - --table-head-fore-color: #ffffff; - --table-body-back-color: #ffffff; - --table-body-fore-color: #03234b; - --table-body-alt-back-color: #f4f4f4; } - -table { - border-collapse: separate; - border-spacing: 0; - margin: 0; - display: flex; - flex: 0 1 auto; - flex-flow: row wrap; - padding: var(--universal-padding); - padding-top: 0; } - table caption { - font-size: 1rem; - margin: calc(2 * var(--universal-margin)) 0; - max-width: 100%; - flex: 0 0 100%; } - table thead, table tbody { - display: flex; - flex-flow: row wrap; - border: 0.0714285714rem solid var(--table-border-color); } - table thead { - z-index: 999; - border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; - border-bottom: 0.0714285714rem solid var(--table-border-separator-color); } - table tbody { - border-top: 0; - margin-top: calc(0 - var(--universal-margin)); - border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } - table tr { - display: flex; - padding: 0; } - table th, table td { - padding: calc(0.5 * var(--universal-padding)); - font-size: 0.9rem; } - table th { - text-align: left; - background: var(--table-head-back-color); - color: var(--table-head-fore-color); } - table td { - background: var(--table-body-back-color); - color: var(--table-body-fore-color); - border-top: 0.0714285714rem solid var(--table-border-color); } - -table:not(.horizontal) { - overflow: auto; - max-height: 100%; } - table:not(.horizontal) thead, table:not(.horizontal) tbody { - max-width: 100%; - flex: 0 0 100%; } - table:not(.horizontal) tr { - flex-flow: row wrap; - flex: 0 0 100%; } - table:not(.horizontal) th, table:not(.horizontal) td { - flex: 1 0 0%; - overflow: hidden; - text-overflow: ellipsis; } - table:not(.horizontal) thead { - position: sticky; - top: 0; } - table:not(.horizontal) tbody tr:first-child td { - border-top: 0; } - -table.horizontal { - border: 0; } - table.horizontal thead, table.horizontal tbody { - border: 0; - flex: .2 0 0; - flex-flow: row nowrap; } - table.horizontal tbody { - overflow: auto; - justify-content: space-between; - flex: .8 0 0; - margin-left: 0; - padding-bottom: calc(var(--universal-padding) / 4); } - table.horizontal tr { - flex-direction: column; - flex: 1 0 auto; } - table.horizontal th, table.horizontal td { - width: auto; - border: 0; - border-bottom: 0.0714285714rem solid var(--table-border-color); } - table.horizontal th:not(:first-child), table.horizontal td:not(:first-child) { - border-top: 0; } - table.horizontal th { - text-align: right; - border-left: 0.0714285714rem solid var(--table-border-color); - border-right: 0.0714285714rem solid var(--table-border-separator-color); } - table.horizontal thead tr:first-child { - padding-left: 0; } - table.horizontal th:first-child, table.horizontal td:first-child { - border-top: 0.0714285714rem solid var(--table-border-color); } - table.horizontal tbody tr:last-child td { - border-right: 0.0714285714rem solid var(--table-border-color); } - table.horizontal tbody tr:last-child td:first-child { - border-top-right-radius: 0.25rem; } - table.horizontal tbody tr:last-child td:last-child { - border-bottom-right-radius: 0.25rem; } - table.horizontal thead tr:first-child th:first-child { - border-top-left-radius: 0.25rem; } - table.horizontal thead tr:first-child th:last-child { - border-bottom-left-radius: 0.25rem; } - -@media screen and (max-width: 499px) { - table, table.horizontal { - border-collapse: collapse; - border: 0; - width: 100%; - display: table; } - table thead, table th, table.horizontal thead, table.horizontal th { - border: 0; - height: 1px; - width: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); } - table tbody, table.horizontal tbody { - border: 0; - display: table-row-group; } - table tr, table.horizontal tr { - display: block; - border: 0.0714285714rem solid var(--table-border-color); - border-radius: var(--universal-border-radius); - background: #ffffff; - padding: var(--universal-padding); - margin: var(--universal-margin); - margin-bottom: calc(1 * var(--universal-margin)); } - table th, table td, table.horizontal th, table.horizontal td { - width: auto; } - table td, table.horizontal td { - display: block; - border: 0; - text-align: right; } - table td:before, table.horizontal td:before { - content: attr(data-label); - float: left; - font-weight: 600; } - table th:first-child, table td:first-child, table.horizontal th:first-child, table.horizontal td:first-child { - border-top: 0; } - table tbody tr:last-child td, table.horizontal tbody tr:last-child td { - border-right: 0; } } -table tr:nth-of-type(2n) > td { - background: var(--table-body-alt-back-color); } - -@media screen and (max-width: 500px) { - table tr:nth-of-type(2n) { - background: var(--table-body-alt-back-color); } } -:root { - --table-body-hover-back-color: #90caf9; } - -table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { - background: var(--table-body-hover-back-color); } - -@media screen and (max-width: 500px) { - table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { - background: var(--table-body-hover-back-color); } } -/* - Definitions for contextual background elements, toasts and tooltips. -*/ -/* Contextual module CSS variable definitions */ -:root { - --mark-back-color: #3cb4e6; - --mark-fore-color: #ffffff; } - -mark { - background: var(--mark-back-color); - color: var(--mark-fore-color); - font-size: 0.95em; - line-height: 1em; - border-radius: var(--universal-border-radius); - padding: calc(var(--universal-padding) / 4) var(--universal-padding); } - mark.inline-block { - display: inline-block; - font-size: 1em; - line-height: 1.4; - padding: calc(var(--universal-padding) / 2) var(--universal-padding); } - -:root { - --toast-back-color: #424242; - --toast-fore-color: #fafafa; } - -.toast { - position: fixed; - bottom: calc(var(--universal-margin) * 3); - left: 50%; - transform: translate(-50%, -50%); - z-index: 1111; - color: var(--toast-fore-color); - background: var(--toast-back-color); - border-radius: calc(var(--universal-border-radius) * 16); - padding: var(--universal-padding) calc(var(--universal-padding) * 3); } - -:root { - --tooltip-back-color: #212121; - --tooltip-fore-color: #fafafa; } - -.tooltip { - position: relative; - display: inline-block; } - .tooltip:before, .tooltip:after { - position: absolute; - opacity: 0; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); - transition: all 0.3s; - z-index: 1010; - left: 50%; } - .tooltip:not(.bottom):before, .tooltip:not(.bottom):after { - bottom: 75%; } - .tooltip.bottom:before, .tooltip.bottom:after { - top: 75%; } - .tooltip:hover:before, .tooltip:hover:after, .tooltip:focus:before, .tooltip:focus:after { - opacity: 1; - clip: auto; - -webkit-clip-path: inset(0%); - clip-path: inset(0%); } - .tooltip:before { - content: ''; - background: transparent; - border: var(--universal-margin) solid transparent; - left: calc(50% - var(--universal-margin)); } - .tooltip:not(.bottom):before { - border-top-color: #212121; } - .tooltip.bottom:before { - border-bottom-color: #212121; } - .tooltip:after { - content: attr(aria-label); - color: var(--tooltip-fore-color); - background: var(--tooltip-back-color); - border-radius: var(--universal-border-radius); - padding: var(--universal-padding); - white-space: nowrap; - transform: translateX(-50%); } - .tooltip:not(.bottom):after { - margin-bottom: calc(2 * var(--universal-margin)); } - .tooltip.bottom:after { - margin-top: calc(2 * var(--universal-margin)); } - -:root { - --modal-overlay-color: rgba(0, 0, 0, 0.45); - --modal-close-color: #e6007e; - --modal-close-hover-color: #ffe97f; } - -[type="checkbox"].modal { - height: 1px; - width: 1px; - margin: -1px; - overflow: hidden; - position: absolute; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); } - [type="checkbox"].modal + div { - position: fixed; - top: 0; - left: 0; - display: none; - width: 100vw; - height: 100vh; - background: var(--modal-overlay-color); } - [type="checkbox"].modal + div .card { - margin: 0 auto; - max-height: 50vh; - overflow: auto; } - [type="checkbox"].modal + div .card .modal-close { - position: absolute; - top: 0; - right: 0; - width: 1.75rem; - height: 1.75rem; - border-radius: var(--universal-border-radius); - padding: var(--universal-padding); - margin: 0; - cursor: pointer; - transition: background 0.3s; } - [type="checkbox"].modal + div .card .modal-close:before { - display: block; - content: '\00D7'; - color: var(--modal-close-color); - position: relative; - font-family: sans-serif; - font-size: 1.75rem; - line-height: 1; - text-align: center; } - [type="checkbox"].modal + div .card .modal-close:hover, [type="checkbox"].modal + div .card .modal-close:focus { - background: var(--modal-close-hover-color); } - [type="checkbox"].modal:checked + div { - display: flex; - flex: 0 1 auto; - z-index: 1200; } - [type="checkbox"].modal:checked + div .card .modal-close { - z-index: 1211; } - -:root { - --collapse-label-back-color: #03234b; - --collapse-label-fore-color: #ffffff; - --collapse-label-hover-back-color: #3cb4e6; - --collapse-selected-label-back-color: #3cb4e6; - --collapse-border-color: var(--collapse-label-back-color); - --collapse-selected-border-color: #ceecf8; - --collapse-content-back-color: #ffffff; - --collapse-selected-label-border-color: #3cb4e6; } - -.collapse { - width: calc(100% - 2 * var(--universal-margin)); - opacity: 1; - display: flex; - flex-direction: column; - margin: var(--universal-margin); - border-radius: var(--universal-border-radius); } - .collapse > [type="radio"], .collapse > [type="checkbox"] { - height: 1px; - width: 1px; - margin: -1px; - overflow: hidden; - position: absolute; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); } - .collapse > label { - flex-grow: 1; - display: inline-block; - height: 1.25rem; - cursor: pointer; - transition: background 0.2s; - color: var(--collapse-label-fore-color); - background: var(--collapse-label-back-color); - border: 0.0714285714rem solid var(--collapse-selected-border-color); - padding: calc(1.25 * var(--universal-padding)); } - .collapse > label:hover, .collapse > label:focus { - background: var(--collapse-label-hover-back-color); } - .collapse > label + div { - flex-basis: auto; - height: 1px; - width: 1px; - margin: -1px; - overflow: hidden; - position: absolute; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); - transition: max-height 0.3s; - max-height: 1px; } - .collapse > :checked + label { - background: var(--collapse-selected-label-back-color); - border-color: var(--collapse-selected-label-border-color); } - .collapse > :checked + label + div { - box-sizing: border-box; - position: relative; - width: 100%; - height: auto; - overflow: auto; - margin: 0; - background: var(--collapse-content-back-color); - border: 0.0714285714rem solid var(--collapse-selected-border-color); - border-top: 0; - padding: var(--universal-padding); - clip: auto; - -webkit-clip-path: inset(0%); - clip-path: inset(0%); - max-height: 100%; } - .collapse > label:not(:first-of-type) { - border-top: 0; } - .collapse > label:first-of-type { - border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; } - .collapse > label:last-of-type:not(:first-of-type) { - border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } - .collapse > label:last-of-type:first-of-type { - border-radius: var(--universal-border-radius); } - .collapse > :checked:last-of-type:not(:first-of-type) + label { - border-radius: 0; } - .collapse > :checked:last-of-type + label + div { - border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } - -/* - Custom elements for contextual background elements, toasts and tooltips. -*/ -mark.tertiary { - --mark-back-color: #3cb4e6; } - -mark.tag { - padding: calc(var(--universal-padding)/2) var(--universal-padding); - border-radius: 1em; } - -/* - Definitions for progress elements and spinners. -*/ -/* Progress module CSS variable definitions */ -:root { - --progress-back-color: #3cb4e6; - --progress-fore-color: #555; } - -progress { - display: block; - vertical-align: baseline; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - height: 0.75rem; - width: calc(100% - 2 * var(--universal-margin)); - margin: var(--universal-margin); - border: 0; - border-radius: calc(2 * var(--universal-border-radius)); - background: var(--progress-back-color); - color: var(--progress-fore-color); } - progress::-webkit-progress-value { - background: var(--progress-fore-color); - border-top-left-radius: calc(2 * var(--universal-border-radius)); - border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } - progress::-webkit-progress-bar { - background: var(--progress-back-color); } - progress::-moz-progress-bar { - background: var(--progress-fore-color); - border-top-left-radius: calc(2 * var(--universal-border-radius)); - border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } - progress[value="1000"]::-webkit-progress-value { - border-radius: calc(2 * var(--universal-border-radius)); } - progress[value="1000"]::-moz-progress-bar { - border-radius: calc(2 * var(--universal-border-radius)); } - progress.inline { - display: inline-block; - vertical-align: middle; - width: 60%; } - -:root { - --spinner-back-color: #ddd; - --spinner-fore-color: #555; } - -@keyframes spinner-donut-anim { - 0% { - transform: rotate(0deg); } - 100% { - transform: rotate(360deg); } } -.spinner { - display: inline-block; - margin: var(--universal-margin); - border: 0.25rem solid var(--spinner-back-color); - border-left: 0.25rem solid var(--spinner-fore-color); - border-radius: 50%; - width: 1.25rem; - height: 1.25rem; - animation: spinner-donut-anim 1.2s linear infinite; } - -/* - Custom elements for progress bars and spinners. -*/ -progress.primary { - --progress-fore-color: #1976d2; } - -progress.secondary { - --progress-fore-color: #d32f2f; } - -progress.tertiary { - --progress-fore-color: #308732; } - -.spinner.primary { - --spinner-fore-color: #1976d2; } - -.spinner.secondary { - --spinner-fore-color: #d32f2f; } - -.spinner.tertiary { - --spinner-fore-color: #308732; } - -/* - Definitions for icons - powered by Feather (https://feathericons.com/). -*/ -span[class^='icon-'] { - display: inline-block; - height: 1em; - width: 1em; - vertical-align: -0.125em; - background-size: contain; - margin: 0 calc(var(--universal-margin) / 4); } - span[class^='icon-'].secondary { - -webkit-filter: invert(25%); - filter: invert(25%); } - span[class^='icon-'].inverse { - -webkit-filter: invert(100%); - filter: invert(100%); } - -span.icon-alert { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12' y2='16'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-bookmark { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z'%3E%3C/path%3E%3C/svg%3E"); } -span.icon-calendar { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-credit { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1' y='4' width='22' height='16' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='1' y1='10' x2='23' y2='10'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-edit { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 14.66V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h5.34'%3E%3C/path%3E%3Cpolygon points='18 2 22 6 12 16 8 16 8 12 18 2'%3E%3C/polygon%3E%3C/svg%3E"); } -span.icon-link { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'%3E%3C/path%3E%3Cpolyline points='15 3 21 3 21 9'%3E%3C/polyline%3E%3Cline x1='10' y1='14' x2='21' y2='3'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-help { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3'%3E%3C/path%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='17' x2='12' y2='17'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-home { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'%3E%3C/path%3E%3Cpolyline points='9 22 9 12 15 12 15 22'%3E%3C/polyline%3E%3C/svg%3E"); } -span.icon-info { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='16' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='8' x2='12' y2='8'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-lock { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2' ry='2'%3E%3C/rect%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'%3E%3C/path%3E%3C/svg%3E"); } -span.icon-mail { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z'%3E%3C/path%3E%3Cpolyline points='22,6 12,13 2,6'%3E%3C/polyline%3E%3C/svg%3E"); } -span.icon-location { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z'%3E%3C/path%3E%3Ccircle cx='12' cy='10' r='3'%3E%3C/circle%3E%3C/svg%3E"); } -span.icon-phone { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z'%3E%3C/path%3E%3C/svg%3E"); } -span.icon-rss { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9'%3E%3C/path%3E%3Cpath d='M4 4a16 16 0 0 1 16 16'%3E%3C/path%3E%3Ccircle cx='5' cy='19' r='1'%3E%3C/circle%3E%3C/svg%3E"); } -span.icon-search { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-settings { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'%3E%3C/circle%3E%3Cpath d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z'%3E%3C/path%3E%3C/svg%3E"); } -span.icon-share { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='18' cy='5' r='3'%3E%3C/circle%3E%3Ccircle cx='6' cy='12' r='3'%3E%3C/circle%3E%3Ccircle cx='18' cy='19' r='3'%3E%3C/circle%3E%3Cline x1='8.59' y1='13.51' x2='15.42' y2='17.49'%3E%3C/line%3E%3Cline x1='15.41' y1='6.51' x2='8.59' y2='10.49'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-cart { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='21' r='1'%3E%3C/circle%3E%3Ccircle cx='20' cy='21' r='1'%3E%3C/circle%3E%3Cpath d='M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6'%3E%3C/path%3E%3C/svg%3E"); } -span.icon-upload { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'%3E%3C/path%3E%3Cpolyline points='17 8 12 3 7 8'%3E%3C/polyline%3E%3Cline x1='12' y1='3' x2='12' y2='15'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-user { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'%3E%3C/path%3E%3Ccircle cx='12' cy='7' r='4'%3E%3C/circle%3E%3C/svg%3E"); } - -/* - Definitions for utilities and helper classes. -*/ -/* Utility module CSS variable definitions */ -:root { - --generic-border-color: rgba(0, 0, 0, 0.3); - --generic-box-shadow: 0 0.2857142857rem 0.2857142857rem 0 rgba(0, 0, 0, 0.125), 0 0.1428571429rem 0.1428571429rem -0.1428571429rem rgba(0, 0, 0, 0.125); } - -.hidden { - display: none !important; } - -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: -1px !important; - border: 0 !important; - padding: 0 !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(100%) !important; - clip-path: inset(100%) !important; - overflow: hidden !important; } - -.bordered { - border: 0.0714285714rem solid var(--generic-border-color) !important; } - -.rounded { - border-radius: var(--universal-border-radius) !important; } - -.circular { - border-radius: 50% !important; } - -.shadowed { - box-shadow: var(--generic-box-shadow) !important; } - -.responsive-margin { - margin: calc(var(--universal-margin) / 4) !important; } - @media screen and (min-width: 500px) { - .responsive-margin { - margin: calc(var(--universal-margin) / 2) !important; } } - @media screen and (min-width: 1280px) { - .responsive-margin { - margin: var(--universal-margin) !important; } } - -.responsive-padding { - padding: calc(var(--universal-padding) / 4) !important; } - @media screen and (min-width: 500px) { - .responsive-padding { - padding: calc(var(--universal-padding) / 2) !important; } } - @media screen and (min-width: 1280px) { - .responsive-padding { - padding: var(--universal-padding) !important; } } - -@media screen and (max-width: 499px) { - .hidden-sm { - display: none !important; } } -@media screen and (min-width: 500px) and (max-width: 1279px) { - .hidden-md { - display: none !important; } } -@media screen and (min-width: 1280px) { - .hidden-lg { - display: none !important; } } -@media screen and (max-width: 499px) { - .visually-hidden-sm { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: -1px !important; - border: 0 !important; - padding: 0 !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(100%) !important; - clip-path: inset(100%) !important; - overflow: hidden !important; } } -@media screen and (min-width: 500px) and (max-width: 1279px) { - .visually-hidden-md { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: -1px !important; - border: 0 !important; - padding: 0 !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(100%) !important; - clip-path: inset(100%) !important; - overflow: hidden !important; } } -@media screen and (min-width: 1280px) { - .visually-hidden-lg { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: -1px !important; - border: 0 !important; - padding: 0 !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(100%) !important; - clip-path: inset(100%) !important; - overflow: hidden !important; } } - -/*# sourceMappingURL=mini-custom.css.map */ - -img[alt="ST logo"] { display: block; margin: auto; width: 75%; max-width: 250px; min-width: 71px; } -img[alt="Cube logo"] { float: right; width: 30%; max-width: 10rem; min-width: 8rem; padding-right: 1rem;} - -.figure { - display: block; - margin-left: auto; - margin-right: auto; - text-align: center; -} diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/st_logo_2020.png b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/_htmresc/st_logo_2020.png deleted file mode 100644 index d6cebb5ac70e0594cbe37a6b60036a80ef3bed37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7520 zcmcI|WmKC@*KTl!K!Z~t6qn*&DDF_CK%q#B6QmH_DHL}I6b%;K-J$eBN|2xh0+bea zmtyV5bG|?CpZBcu=iF<}z4q*xz1LhL*PcBwx;m;Pgmi=e0DweYO-UaBz)*UWZ}4#+ zCC-V!SC16}H#HLv0Dy?%--0o{5_}H;Jf%=ql7H=+dziOk_)KzUSaiQ9L<^g!49k}} z?4y$V zrsn3Ul^TY`00G_J_8;F7Sr5c3Y)f-yOYl{fS0avfKJg7R%r!y-ohcBkr6XBZBkE)( z_t+tVV2}G1_CN!)yWes*wa-AGwk31N_T1`)4COlfz+o(9S90e?6jHV4)!>`j+oRqp z)gb?rtSdw<#&c?q!OKB+Ncn!kr5JR2EYan8HAPXBw*Oh-F(6GmaC!`$p7fl!_Cdu> z5@PUMR_K5&jgevDepWqepZVdMHR$q>ga=7k0ltW$HHVn>HRa!#(+BW_jN$5rx^MtR zzWT7tNWQeFzEp+86jOYI=I)*GZYEiXlf-Mw%tJ^ptL%2)%#PmUjxC4wx@%KxQ)8kO?|7E1 zd@5gd9_$*6nx?fj*iF_EJT*PYLFP}d8*Fw>cu3@&nm%V_C}V7HMmg|Nl#1J1^#)uz zZag|X>{6j-myvL}3(H8o3resNBq_jcuJuyT!QuXnNN&zG^tG? z>y*dy1#XfwyCE#UiLT(~LYAVwp)epErJLsHBA|l0xo)kxLAPob+7tFlr{7x8(#v|O zknK}QC6|~=cTJ0;x9MWMKua;LdTKIHX>35a@7{5y0MQ|zqsP64mM~`gJ&&R{pSUBA zf3Y>k>d|xdzBFztjtO~{y%@LUdwSgzEj=69hH3-NNWx7<|49%2%lvTEeE3_|$~iDd zlktnxf|NB>Bui)yY;%TXgWA;rhODxR!-4GzxKd473I)3;j zS4-Vun<^vqZ4)HbwVzq%5%)S!>Q(Y&PkF ze1ab_oy?_$PZT-mKJ3K^;6MrB*Wc$lkYJ_460AFYEq{AjlDxm;5GRwOsm>doJy3Z;a$FSu-q`X)Hw&o~?_`Dnpx4dOj6#)bGOdZbj4hD`l|&#v~K+WrGO zpLCVQg=*h=4H1sK)D*Pxtb#p`c+g-eK65k!CEZjLIrfm}5<4@KVqZ#8(S$vs{?Xv) zN(}CKeeLR%I)W!p(l-`utKmBbJk-On{)ciqUN5%?TS8uwKU(8}Mxhsb&qHL~DDcB@qi} z4z%efV#K69a#lShPt5}*7ME@^xunFR{k;|qp z`_Hgdj_Qle?%Ydlr3f^SdRkUncIj7qTiu85tA$v`#419Nlof8tjqUjO z!Rwyq$Krfh`(@MiE+)yie&jU^crprYV&?zN!2b33S2qtW+zB$nahDhVZiQ12bmcwYBcT8KS>v`jsuI@X zy^k^7>TM5Ndp@}pSl6vmkk*u`@C`z(gq||K2>y=Y#w1i`Nk2zAP7{_^ACq;bQmT<4 z;b~K3=?mhZX#~jQnZjdU={NFp^HRr~;^PXQ*UIHzkq}Xsn!56*ZCOOEt|^ zawUwGqs;zCEGKTz&(a(@h#0sCE+@`3Y<&}9!(;Pw&`C+d#D?`##&!@*ERaH0fksrh zfk2svh3!d~h{SC6BNKN2j6(lzC>S^_*eh{@gR zP$rV4$nqV1y|zYpd;nQr-`Vlp(5sQXx9AibC?xc7pUV)v2cWfHu3{KLbfP;;;`I&)mWqLcXt6s+5fps9R?K>hGR$5;=( zo#;zzQ5!w+(99p1_gh^?F#$tpMd+4%G|K`XG_#@A>30WD2L9!0a>wRASg`M?^z#)| zifb$d^KUD&3qLsr-@}r_7p${gdmRqhy819bj?yI-v({I?0o3_8d>CZmCzqH4{{QtD z|6dvgm<^~668G`6wLw4C4y-o9E9ZG3RiH^&;rrKSBT@bMR+!TlYo*9P;?Z>xORMV3ndQp9EyNn!!~j&x&$gDVke|t#!{QoegHm+sT7cSjwSu z)jZlx1pHrrx0&YCZWJ4xC&U%r_IwfJOxnYqYMcZn&_hgnKuls z>(Y$qjIhcweo^A_VVq_#UR&urF%UbI^><5L5zbV9owMQviM*_{@i|dke!!v8a_yG! zl%#ay{(6U_N3-)yeif3tx6>aQSf1r zO~OuNW<8a~bi6Xby0@tKw0@f1R!@+3S2nf#F&j~l0mrNCtjoZdPYob?g!Vx4F-uA2 z4uS>8eR?dA9i>C|cm-m5lO0m@$f(DB6Z<9Pe07xR`l4$ks3eZ@v5}1?^YNQy-tB(` zgUNZrGVf#b~`}jew;MQG1O~VDk_i*<)p9DfFfd;vLy4QZT zMYh|DxJg3-!{szUN*uo&`&DUkzq4qG2`Lj;Ar46DYUymcviS{Unhzmx z=LwZ-Lr{t1z?9Oip%!z{j+Z%_@u?C78I`V4fC`icG1c|2;`EoLK$ z)9|wrAV&V1Vgts~tQCw0X?X{74W"NJQ zW3BP!5c~4zzHJScwQK9L_%m%L`*q{1aW_3rObki~B~=Dwp`;@w`>xZ6;L_6oR^ecEcmup`yb}lgsmv zQByrxc)Qqm(Hwmq%fLjqcrJ5QR?z_*vb~Iy~RXUY8u-D8AqTzetwNNA8~N z$j&1>#IrkSslUqXW|l}q_TlTVKAjRI@~7(GLf4M>GM!3u_)y6ORe6BQUmrQ16%OdZKo(?AYXK$u@=)TPUi1EZaLBu zuEB(5GX2vcoHS%zMUW!DZ)&xRo@mhouk|hMgHIG>cO-Ah(0AMNlq@?cPpy==-!#qR zBov7l3G?P*KM(vU;Apo-(-Bw;sdQJkh~r)W$KRQKd!#(A8M34^MhD10Ra={AqSvjy z3>PkgA}f^@Rg1$dX=jaEB_V%_vn(W<111_s!g>CYrcwJTJ63Eeg6{_C`aMQIgKctR zHMjkr+y6gK!v6=6;CGl#?PqmiX`A@dmmvZ}-X$*q8}G(xq|voo`=$YZuQAa8f9ApK z1VQiEUQC=OO{|Nc8ZrXH208X|XCzIRO?+Nb55Jt@va9hqBpv)uY6ma-csvSlJoJOC zK;w~s?#r)K@gm*;((JsWHU-KvFTF)q>AzwPq)I+}OrSpxh!-CM1VEMfw1fpfVL7p{ z)I$rNp5kPYDsvXL>8nV{#0fa*lm`Z;0Z=c^1qveY2uk&7nhMRl`0EsvUuvwdF&o)PCVN3wmFBPegWzooF6y~b} zY>X2;LO~&rbvx59?(4^aR+s1C6hI4r&x9Q9jL9);KZEw_x%TWZXaMzK6|2XG9$IU% zkEq}t^YOaa4s`%7F31X-#SfMgNp+4R=g2G|O^W)6^2fEsmkTTaVhKCip+3qWuN8?y zaSD_k6%-@Ifhm`z02=ZWA-pi5`A=7ztHWpP2K5rCW{>!wIUOYrH``#bz>qVSH76=8 zyJ!sNBxt;dMTn}yzUTCq1!w;N7pzb?WJrQ50W+`meL{k8i0VhFsPUz(07k`l` zg1Ifl1fc-^p^MQCpK~Jk&L!*mWfNA!&MSu`sPmti>K-;I5Dk00nB3vOl4!JwjEx^X zWQsIp2Ea_>`9f@%zGl4i3FAO9=e$2^b_>_I*dqiLJ=@TejStM?^yX$9dW`#ha)PEF zPr0zUJX!j-juYK*olG_9axQniXhF|E}oSTG_S)FZ3sN4T@q zy{l;!{UGc};YVaT97tx3s7P$WsW2^*I+Hy;vqndG!9S?tZtDIRif1=bBsqtW-n7$O zWy}Z%jKSkgLX#1p>|#4l-!$c+kA`++Ixv(Rm`;Ilb3q3tD|QjaPQ8)BJ=8R*15?nL zJR{yuqOG&!JrSZ${#NY#b!k)yDajQ$A}fUQhe7ueN6h2Pj3wY5eo|7$PaJD zM69(ee1qlSyLn)Ln6)o53Lj)elqG}gb^c}qd(q&$8B5N%nSvEjUIoEXO^obv=A7QGZzNzjO*H=*b2!86Wnqdy~8ePkq@1D1)Q^O)JG;fUCV z`rgD}dJ{7BUyBbgoTL91w^q-CfBpDr?0R38`L%p9&Q#%r*@=9p-Ioqy+WscLq?jq5 zfyYNkxr7w)-(!c85mt!FjNJ4UE6P8p8sc#Kb4L1N3!yaCo9@t3n8s}K)1!w8x77xU zo-NY3SR*Pgt#~7F;y^J&Y%z^+C9wu;hN|TC7dqSHOB&kE)Q)6Ad(l&+tA@$@w0bhJ z6xc6EJ6nm{=|V7Vo&qcXc4i)D?X0Uk$p7~iI#ci?#fxvM z78`u%m5S@^_F;_foidufzP z&ueh-zU1yM&8~0lmOfkio-gBex`)?hCJcI8Jv*R0c|WUqSq z?RU?Rmm=3t_2C%%UW9c*D%T{T{EjryCKnsz9-*Bs0}M*xS&-odhCK5eS_Eqi&c6J4o|f&;uUT=p7Fedw#EUl4%Jv{w zq-cCF^otBvw~~$yj6O>>;VqU)3Ml&Atm$B(Ht8=+&x2VS5aWD&t*+04{@k^Gn~yHY zWYC%@ld;g_qz=k*;Iv&xs5M85cEZCU&n2Baf>R6*bN>V|!)eF&l#C93eAMLD=ZF7= zOISFfB5P;F!ngWD3jfMJE_53F&dFc{h2TwSbT*(h6!c}_5_UFeB_*DiyCrtQ7Byr@ z-aCWVt?J}YP7-lfelbrCgZ5mdv(^W&Yf^OvpI}#NbS1Lc`r4&t#3kM!utm&#a;?GR z-1FusfX7&?a9h`%8wf-ub7UXp44xm4w04)S$}}_hPqn-#IabO^bo6$K07>?%G5Xs( zA$*lz_K>lAJ_o<;fsP-*-%~O(716KRqVq+X@=5J~Z~bba(yWL`;EN`@Mr2it&Lkgb z&I|R5!`ZSk%)xFX*FYDaAh=5qWSY@rx1Du9J$$=lh#!~NcFJM&aOv)eqg_@`i^zJCR9a%_{k_i%msw5q z*3!~#Xx3r|VaAwiG}~9M#c`=$Uk6~xe)47ymW+;0DD_lV67L#ouJBa7mF{)X^?eIvPdOMu4ksr`jUP$~{x@?ev2 zdX#ite2RMim01PEg`;qfwg^;v8nx9F!CtNCvz)V{PVgCs*;_@_Rk*oLx@f7hJ7^^1 zu66b)mb!ZMXLZ%8dj-+JCMoWS-Wji-Q-~U7Pt~UiXMej8JcNjk<6?Wk9eLBIhu&Vo^0;AH> z;Q5^a!NZhP(vDfBv&?jdnQavv#8N0E{ZEgs>|1)qYo^t5 zIV$g~`C2%g$*(z4)8hJlK2mF-MJW#3%Cs6`uAvsgRtTo8n!Et)1pZx@_9I18 zw7ER9v~DyrC*R$do9aEw5r@B)YzHOLB^-c9Eu9D!sFmI8^VljVKE89{zY_8PTSF+J b^}%0^qYmp2WD(pA|JtZ4>nPPKybJpu3@X?! diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c deleted file mode 100644 index 952ff16c9..000000000 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.c +++ /dev/null @@ -1,886 +0,0 @@ -/** - ****************************************************************************** - * @file tcpp0203.c - * @author MCD Application Team - * @brief This file provides the TCPP02/03 Type-C port protection driver. - ****************************************************************************** - * @attention - * - * Copyright (c) 2021 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "tcpp0203.h" - -#if defined(_TRACE) -#include "usbpd_core.h" -#include "usbpd_trace.h" -#include "string.h" -#include "stdio.h" -#endif /* _TRACE */ - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup Components - * @{ - */ - -/** @addtogroup TCPP0203 - * @brief This file provides a set of functions needed to drive the - * TCPP02/03 Type-C port protection. - * @{ - */ - -/** @defgroup TCPP0203_Private_Constants Private Constants - * @{ - */ - -/* Compilation option in order to enable/disable a concistency check performed - after each I2C access into TCPP0203 registers : goal is to check that written value in Reg0 - is properly reflected into reg1 register content. - To enable register consistency check, please uncomment below definition. - To disable it, comment below line */ -/* #define TCPP0203_REGISTER_CONSISTENCY_CHECK */ - -/** @defgroup TCPP0203_Private_Types Private Types - * @{ - */ -/* TCPP02/03 Type-C port protection driver structure initialization */ -TCPP0203_Drv_t TCPP0203_Driver = -{ - TCPP0203_Init, - TCPP0203_DeInit, - TCPP0203_Reset, - TCPP0203_SetVConnSwitch, - TCPP0203_SetGateDriverProvider, - TCPP0203_SetGateDriverConsumer, - TCPP0203_SetPowerMode, - TCPP0203_SetVBusDischarge, - TCPP0203_SetVConnDischarge, - TCPP0203_GetVConnSwitchAck, - TCPP0203_GetGateDriverProviderAck, - TCPP0203_GetGateDriverConsumerAck, - TCPP0203_GetPowerModeAck, - TCPP0203_GetVBusDischargeAck, - TCPP0203_GetVConnDischargeAck, - TCPP0203_GetOCPVConnFlag, - TCPP0203_GetOCPVBusFlag, - TCPP0203_GetOVPVBusFlag, - TCPP0203_GetOVPCCFlag, - TCPP0203_GetOTPFlag, - TCPP0203_GetVBusOkFlag, - TCPP0203_ReadTCPPType, - TCPP0203_ReadVCONNPower, - TCPP0203_WriteCtrlRegister, - TCPP0203_ReadAckRegister, - TCPP0203_ReadFlagRegister, -}; - -/** - * @} - */ - -/** @defgroup TCPP0203_Private_Variables Private Variables - * @{ - */ -static uint8_t TCPP0203_DeviceType = TCPP0203_DEVICE_TYPE_03; - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) -static uint8_t Reg0_Expected_Value = 0x00; -static uint8_t Reg1_LastRead_Value = 0x00; -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - -/** - * @} - */ - -/* Private function prototypes -----------------------------------------------*/ - -/** @defgroup TCPP0203_Private_Function_Prototypes TCPP0203 Private Function Prototypes - * @{ - */ -static int32_t TCPP0203_ReadRegWrap(const void *handle, uint8_t Reg, uint8_t *Data, uint8_t Length); -static int32_t TCPP0203_WriteRegWrap(const void *handle, uint8_t Reg, uint8_t *Data, uint8_t Length); - -static int32_t TCPP0203_ModifyReg0(TCPP0203_Object_t *pObj, uint8_t Value, uint8_t Mask); - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) -static int32_t TCPP0203_CheckReg0Reg1(TCPP0203_Object_t *pObj, uint8_t Reg0ExpectedValue); -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - -/** - * @} - */ - -/** @defgroup TCPP0203_Exported_Functions TCPP0203 Exported Functions - * @{ - */ - -/** - * @brief Register Bus Io to component - * @param Component object pointer - * @retval Status of execution - */ -int32_t TCPP0203_RegisterBusIO(TCPP0203_Object_t *pObj, TCPP0203_IO_t *pIO) -{ - int32_t ret; - - if (pObj == NULL) - { - ret = TCPP0203_ERROR; - } - else - { - pObj->IO.Init = pIO->Init; - pObj->IO.DeInit = pIO->DeInit; - pObj->IO.Address = pIO->Address; - pObj->IO.WriteReg = pIO->WriteReg; - pObj->IO.ReadReg = pIO->ReadReg; - pObj->IO.GetTick = pIO->GetTick; - - pObj->Ctx.ReadReg = TCPP0203_ReadRegWrap; - pObj->Ctx.WriteReg = TCPP0203_WriteRegWrap; - pObj->Ctx.handle = pObj; - - if (pObj->IO.Init != NULL) - { - ret = pObj->IO.Init(); - } - else - { - ret = TCPP0203_ERROR; - } - } - - return ret; -} - -/** - * @brief Initializes the TCPP0203 interface - * @param pObj Pointer to component object - * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) - */ -int32_t TCPP0203_Init(TCPP0203_Object_t *pObj) -{ - int32_t ret = 0; - uint8_t tmp; - - if (pObj->IsInitialized == 0U) - { - /* Read TCPP Device type */ - ret += tcpp0203_read_reg(&pObj->Ctx, TCPP0203_READ_REG2, &tmp, 1); - - if (ret == TCPP0203_OK) - { - TCPP0203_DeviceType = (tmp & TCPP0203_DEVICE_TYPE_MSK); - } - else - { - TCPP0203_DeviceType = TCPP0203_DEVICE_TYPE_02; - } - pObj->IsInitialized = 1U; - } - - if (ret != TCPP0203_OK) - { - ret = TCPP0203_ERROR; - } - - return ret; -} - -/** - * @brief Deinitializes the TCPP0203 interface - * @param pObj Pointer to component object - * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) - */ -int32_t TCPP0203_DeInit(TCPP0203_Object_t *pObj) -{ - if (pObj->IsInitialized == 1U) - { - /* De-Initialize IO BUS layer */ - pObj->IO.DeInit(); - - pObj->IsInitialized = 0U; - } - - return TCPP0203_OK; -} - -/** - * @brief Resets TCPP0203 register (Reg0) - * @param pObj Pointer to component object - * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) - */ -int32_t TCPP0203_Reset(TCPP0203_Object_t *pObj) -{ - int32_t ret = TCPP0203_OK; - uint8_t tmp = TCPP0203_REG0_RST_VALUE; - - /* Write reset values in Reg0 register */ - if (tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, &tmp, 1) != TCPP0203_OK) - { - ret = TCPP0203_ERROR; - } - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) - Reg0_Expected_Value = TCPP0203_REG0_RST_VALUE; - Reg1_LastRead_Value = TCPP0203_REG0_RST_VALUE; -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - - return ret; -} - -/** - * @brief Configure TCPP0203 VConn Switch - * @param pObj Pointer to component object - * @param VConnSwitch VConn Switch requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_VCONN_SWITCH_OPEN VConn switch open - * @arg TCPP0203_VCONN_SWITCH_CC1 VConn closed on CC1 - * @arg TCPP0203_VCONN_SWITCH_CC2 VConn closed on CC2 - * @retval Component status - */ -int32_t TCPP0203_SetVConnSwitch(TCPP0203_Object_t *pObj, uint8_t VConnSwitch) -{ - int32_t ret = TCPP0203_OK; - - if ((VConnSwitch != TCPP0203_VCONN_SWITCH_OPEN) - && (VConnSwitch != TCPP0203_VCONN_SWITCH_CC1) - && (VConnSwitch != TCPP0203_VCONN_SWITCH_CC2)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update VConn switch setting in Writing register Reg0 */ - ret += TCPP0203_ModifyReg0(pObj, VConnSwitch, TCPP0203_VCONN_SWITCH_MSK); - } - - return ret; -} - -/** - * @brief Configure TCPP0203 Gate Driver for Provider path - * @param pObj Pointer to component object - * @param GateDriverProvider GDP switch load requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_GD_PROVIDER_SWITCH_OPEN GDP Switch Load Open - * @arg TCPP0203_GD_PROVIDER_SWITCH_CLOSED GDP Switch Load closed - * @retval Component status - */ -int32_t TCPP0203_SetGateDriverProvider(TCPP0203_Object_t *pObj, uint8_t GateDriverProvider) -{ - int32_t ret = TCPP0203_OK; - - if ((GateDriverProvider != TCPP0203_GD_PROVIDER_SWITCH_OPEN) - && (GateDriverProvider != TCPP0203_GD_PROVIDER_SWITCH_CLOSED)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update GDP Switch Load setting in Writing register Reg0 */ - if (GateDriverProvider == TCPP0203_GD_PROVIDER_SWITCH_CLOSED) - { - /* If Gate Driver Provider is to be closed, Gate Driver Consumer should be open */ - ret += TCPP0203_ModifyReg0(pObj, (GateDriverProvider | TCPP0203_GD_CONSUMER_SWITCH_OPEN), - (TCPP0203_GD_PROVIDER_SWITCH_MSK | TCPP0203_GD_CONSUMER_SWITCH_MSK)); - } - else - { - ret += TCPP0203_ModifyReg0(pObj, GateDriverProvider, TCPP0203_GD_PROVIDER_SWITCH_MSK); - } - } - - return ret; -} - -/** - * @brief Configure TCPP0203 Gate Driver for Consumer path - * @param pObj Pointer to component object - * @param GateDriverConsumer GDC switch load requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_GD_CONSUMER_SWITCH_OPEN GDC Switch Load Open - * @arg TCPP0203_GD_CONSUMER_SWITCH_CLOSED GDC Switch Load closed - * @retval Component status - */ -int32_t TCPP0203_SetGateDriverConsumer(TCPP0203_Object_t *pObj, uint8_t GateDriverConsumer) -{ - int32_t ret = TCPP0203_OK; - - /* Check if TCPP type is TCPP03. Otherwise, return error */ - if (TCPP0203_DeviceType != TCPP0203_DEVICE_TYPE_03) - { - return (TCPP0203_ERROR); - } - - if ((GateDriverConsumer != TCPP0203_GD_CONSUMER_SWITCH_OPEN) - && (GateDriverConsumer != TCPP0203_GD_CONSUMER_SWITCH_CLOSED)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update GDC Switch Load setting in Writing register Reg0 */ - if (GateDriverConsumer == TCPP0203_GD_CONSUMER_SWITCH_CLOSED) - { - /* If Gate Driver Consumer is to be closed, Gate Driver Provider should be open */ - ret += TCPP0203_ModifyReg0(pObj, (GateDriverConsumer | TCPP0203_GD_PROVIDER_SWITCH_OPEN), - (TCPP0203_GD_PROVIDER_SWITCH_MSK | TCPP0203_GD_CONSUMER_SWITCH_MSK)); - } - else - { - ret += TCPP0203_ModifyReg0(pObj, GateDriverConsumer, TCPP0203_GD_CONSUMER_SWITCH_MSK); - } - } - - return ret; -} - -/** - * @brief Configure TCPP0203 Power Mode - * @param pObj Pointer to component object - * @param PowerMode Power mode requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_POWER_MODE_HIBERNATE Hibernate - * @arg TCPP0203_POWER_MODE_LOWPOWER Low Power - * @arg TCPP0203_POWER_MODE_NORMAL Normal - * @retval Component status - */ -int32_t TCPP0203_SetPowerMode(TCPP0203_Object_t *pObj, uint8_t PowerMode) -{ - int32_t ret = TCPP0203_OK; - - if ((PowerMode != TCPP0203_POWER_MODE_HIBERNATE) - && (PowerMode != TCPP0203_POWER_MODE_LOWPOWER) - && (PowerMode != TCPP0203_POWER_MODE_NORMAL)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update Power Mode setting in Writing register Reg0 */ - ret += TCPP0203_ModifyReg0(pObj, PowerMode, TCPP0203_POWER_MODE_MSK); - } - - return ret; -} - -/** - * @brief Configure TCPP0203 Gate Driver for Provider path - * @param pObj Pointer to component object - * @param VBusDischarge VBUS Discharge requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_VBUS_DISCHARGE_OFF VBUS Discharge Off - * @arg TCPP0203_VBUS_DISCHARGE_ON VBUS Discharge On - * @retval Component status - */ -int32_t TCPP0203_SetVBusDischarge(TCPP0203_Object_t *pObj, uint8_t VBusDischarge) -{ - int32_t ret = TCPP0203_OK; - - if ((VBusDischarge != TCPP0203_VBUS_DISCHARGE_OFF) - && (VBusDischarge != TCPP0203_VBUS_DISCHARGE_ON)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update VBUS Discharge setting in Writing register Reg0 */ - ret += TCPP0203_ModifyReg0(pObj, VBusDischarge, TCPP0203_VBUS_DISCHARGE_MSK); - } - - return ret; -} - -/** - * @brief Configure TCPP0203 Gate Driver for Provider path - * @param pObj Pointer to component object - * @param VConnDischarge GDP switch load requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_VCONN_DISCHARGE_OFF VConn Discharge Off - * @arg TCPP0203_VCONN_DISCHARGE_ON VConn Discharge On - * @retval Component status - */ -int32_t TCPP0203_SetVConnDischarge(TCPP0203_Object_t *pObj, uint8_t VConnDischarge) -{ - int32_t ret = TCPP0203_OK; - - if ((VConnDischarge != TCPP0203_VCONN_DISCHARGE_OFF) - && (VConnDischarge != TCPP0203_VCONN_DISCHARGE_ON)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update VConn Discharge setting in Writing register Reg0 */ - ret += TCPP0203_ModifyReg0(pObj, VConnDischarge, TCPP0203_VCONN_DISCHARGE_MSK); - } - - return ret; -} - -/** - * @brief Get VConn switch Ack value - * @param pObj Pointer to component object - * @param pVConnSwitchAck Pointer on VConn switch Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_VCONN_SWITCH_OPEN VConn switch open Ack - * @arg TCPP0203_VCONN_SWITCH_CC1 VConn closed on CC1 Ack - * @arg TCPP0203_VCONN_SWITCH_CC2 VConn closed on CC2 Ack - * @retval Component status - */ -int32_t TCPP0203_GetVConnSwitchAck(TCPP0203_Object_t *pObj, uint8_t *pVConnSwitchAck) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pVConnSwitchAck = (tmp & TCPP0203_VCONN_SWITCH_ACK_MSK); - - return ret; -} - -/** - * @brief Get Gate Driver Provider Ack value - * @param pObj Pointer to component object - * @param pGateDriverProviderAck Pointer on Gate Driver Provider Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_GD_PROVIDER_SWITCH_ACK_OPEN Gate Driver Provider Open Ack - * @arg TCPP0203_GD_PROVIDER_SWITCH_ACK_CLOSED Gate Driver Provider Closed Ack - * @retval Component status - */ -int32_t TCPP0203_GetGateDriverProviderAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverProviderAck) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pGateDriverProviderAck = (tmp & TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK); - - return ret; -} - -/** - * @brief Get Gate Driver Consumer Ack value - * @param pObj Pointer to component object - * @param pGateDriverConsumerAck Pointer on Gate Driver Consumer Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_GD_CONSUMER_SWITCH_ACK_OPEN Gate Driver Consumer Open Ack - * @arg TCPP0203_GD_CONSUMER_SWITCH_ACK_CLOSED Gate Driver Consumer Closed Ack - * @retval Component status - */ -int32_t TCPP0203_GetGateDriverConsumerAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverConsumerAck) -{ - int32_t ret; - uint8_t tmp; - - /* Check if TCPP type is TCPP03. Otherwise, return error */ - if (TCPP0203_DeviceType != TCPP0203_DEVICE_TYPE_03) - { - return (TCPP0203_ERROR); - } - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pGateDriverConsumerAck = (tmp & TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK); - - return ret; -} - -/** - * @brief Get Power Mode Ack value - * @param pObj Pointer to component object - * @param pPowerModeAck Pointer on Power Mode Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_POWER_MODE_ACK_HIBERNATE Power Mode Hibernate Ack - * @arg TCPP0203_POWER_MODE_ACK_LOWPOWER Power Mode Low Power Ack - * @arg TCPP0203_POWER_MODE_ACK_NORMAL Power Mode Normal Ack - * @retval Component status - */ -int32_t TCPP0203_GetPowerModeAck(TCPP0203_Object_t *pObj, uint8_t *pPowerModeAck) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pPowerModeAck = (tmp & TCPP0203_POWER_MODE_ACK_MSK); - - return ret; -} - -/** - * @brief Get VBUS Discharge Ack value - * @param pObj Pointer to component object - * @param pVBusDischargeAck Pointer on VBUS Discharge Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_VBUS_DISCHARGE_ACK_OFF VBUS Discharge Off Ack - * @arg TCPP0203_VBUS_DISCHARGE_ACK_ON VBUS Discharge On Ack - * @retval Component status - */ -int32_t TCPP0203_GetVBusDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVBusDischargeAck) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pVBusDischargeAck = (tmp & TCPP0203_VBUS_DISCHARGE_ACK_MSK); - - return ret; -} - -/** - * @brief Get VConn Discharge Ack value - * @param pObj Pointer to component object - * @param pVConnDischargeAck Pointer on VConn Discharge Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_VCONN_DISCHARGE_ACK_OFF VConn Discharge Off Ack - * @arg TCPP0203_VCONN_DISCHARGE_ACK_ON VConn Discharge On Ack - * @retval Component status - */ -int32_t TCPP0203_GetVConnDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVConnDischargeAck) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pVConnDischargeAck = (tmp & TCPP0203_VCONN_DISCHARGE_ACK_MSK); - - return ret; -} - -/** - * @brief Get OCP VConn Flag value - * @param pObj Pointer to component object - * @param pOCPVConnFlag Pointer on OCP VConn Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_OCP_VCONN_RESET OCP VConn flag not set - * @arg TCPP0203_FLAG_OCP_VCONN_SET OCP VConn flag set - * @retval Component status - */ -int32_t TCPP0203_GetOCPVConnFlag(TCPP0203_Object_t *pObj, uint8_t *pOCPVConnFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pOCPVConnFlag = (tmp & TCPP0203_FLAG_OCP_VCONN_MSK); - - return ret; -} - -/** - * @brief Get OCP VBUS Flag value - * @param pObj Pointer to component object - * @param pGetOCPVBusFlag Pointer on OCP VBUS Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_OCP_VBUS_RESET OCP VBUS flag not set - * @arg TCPP0203_FLAG_OCP_VBUS_SET OCP VBUS flag set - * @retval Component status - */ -int32_t TCPP0203_GetOCPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pGetOCPVBusFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pGetOCPVBusFlag = (tmp & TCPP0203_FLAG_OCP_VBUS_MSK); - - return ret; -} - -/** - * @brief Get OVP VBUS Flag value - * @param pObj Pointer to component object - * @param pOVPVBusFlag Pointer on OVP VBUS Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_OVP_VBUS_RESET OVP VBUS flag not set - * @arg TCPP0203_FLAG_OVP_VBUS_SET OVP VBUS flag set - * @retval Component status - */ -int32_t TCPP0203_GetOVPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPVBusFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pOVPVBusFlag = (tmp & TCPP0203_FLAG_OVP_VBUS_MSK); - - return ret; -} - -/** - * @brief Get OVP CC Flag value - * @param pObj Pointer to component object - * @param pOVPCCFlag Pointer on OVP CC Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_OVP_CC_RESET OVP CC flag not set - * @arg TCPP0203_FLAG_OVP_CC_SET OVP CC flag set - * @retval Component status - */ -int32_t TCPP0203_GetOVPCCFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPCCFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pOVPCCFlag = (tmp & TCPP0203_FLAG_OVP_CC_MSK); - - return ret; -} - -/** - * @brief Get Over Temperature Flag value - * @param pObj Pointer to component object - * @param pOTPFlag Pointer on Over Temperature Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_OTP_RESET Over Temperature flag not set - * @arg TCPP0203_FLAG_OTP_SET Over Temperature flag set - * @retval Component status - */ -int32_t TCPP0203_GetOTPFlag(TCPP0203_Object_t *pObj, uint8_t *pOTPFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pOTPFlag = (tmp & TCPP0203_FLAG_OTP_MSK); - - return ret; -} - -/** - * @brief Get VBUS OK Flag value - * @param pObj Pointer to component object - * @param pVBusOkFlag Pointer on VBUS OK Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_VBUS_OK_RESET VBUS OK flag not set - * @arg TCPP0203_FLAG_VBUS_OK_SET VBUS OK flag set - * @retval Component status - */ -int32_t TCPP0203_GetVBusOkFlag(TCPP0203_Object_t *pObj, uint8_t *pVBusOkFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pVBusOkFlag = (tmp & TCPP0203_FLAG_VBUS_OK_MSK); - - return ret; -} - -/** - * @brief Get TCPP0203 Device Type value - * @param pObj Pointer to component object - * @param pTCPPType Pointer on TCPP0203 Device Type value - * This output parameter can be one of the following values: - * @arg TCPP0203_DEVICE_TYPE_02 TCPP02 Type - * @arg TCPP0203_DEVICE_TYPE_03 TCPP03 Type - * @retval Component status - */ -int32_t TCPP0203_ReadTCPPType(TCPP0203_Object_t *pObj, uint8_t *pTCPPType) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pTCPPType = (tmp & TCPP0203_DEVICE_TYPE_MSK); - - return ret; -} - -/** - * @brief Get VConn Power value - * @param pObj Pointer to component object - * @param pVCONNPower Pointer on VConn Power value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_VCONN_PWR_1W OCP VConn flag not set - * @arg TCPP0203_FLAG_VCONN_PWR_0_1W OCP VConn flag set - * @retval Component status - */ -int32_t TCPP0203_ReadVCONNPower(TCPP0203_Object_t *pObj, uint8_t *pVCONNPower) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pVCONNPower = (tmp & TCPP0203_FLAG_VCONN_PWR_MSK); - - return ret; -} - -/** - * @brief Set complete Ctrl register value (Reg 0) - * @param pObj Pointer to component object - * @param pCtrlRegister Pointer on Ctrl register value - * @retval Component status - */ -int32_t TCPP0203_WriteCtrlRegister(TCPP0203_Object_t *pObj, uint8_t *pCtrlRegister) -{ - int32_t ret; - - /* Update value in writing register (reg0) */ - ret = tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, pCtrlRegister, 1); - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) - Reg0_Expected_Value = *pCtrlRegister; -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - - return ret; -} - -/** - * @brief Get complete Ack register value - * @param pObj Pointer to component object - * @param pAckRegister Pointer on Ack register value - * @retval Component status - */ -int32_t TCPP0203_ReadAckRegister(TCPP0203_Object_t *pObj, uint8_t *pAckRegister) -{ - int32_t ret; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, pAckRegister, 1); - - return ret; -} - -/** - * @brief Get complete Flag register value - * @param pObj Pointer to component object - * @param pFlagRegister Pointer on Flag register value - * @retval Component status - */ -int32_t TCPP0203_ReadFlagRegister(TCPP0203_Object_t *pObj, uint8_t *pFlagRegister) -{ - int32_t ret; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, pFlagRegister, 1); - - return ret; -} - -/******************** Static functions ****************************************/ -/** - * @brief Wrap TCPP0203 read function to Bus IO function - * @param handle Component object handle - * @param Reg Target register address to read - * @param pData Buffer where Target register value should be stored - * @param Length buffer size to be read - * @retval error status - */ -static int32_t TCPP0203_ReadRegWrap(const void *handle, uint8_t Reg, uint8_t *pData, uint8_t Length) -{ - const TCPP0203_Object_t *pObj = (const TCPP0203_Object_t *)handle; - - return pObj->IO.ReadReg(pObj->IO.Address, Reg, pData, Length); -} - -/** - * @brief Wrap TCPP0203 write function to Bus IO function - * @param handle Component object handle - * @param Reg Target register address to write - * @param pData Target register value to be written - * @param Length Buffer size to be written - * @retval error status - */ -static int32_t TCPP0203_WriteRegWrap(const void *handle, uint8_t Reg, uint8_t *pData, uint8_t Length) -{ - const TCPP0203_Object_t *pObj = (const TCPP0203_Object_t *)handle; - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) - Reg0_Expected_Value = *pData; -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - - return pObj->IO.WriteReg(pObj->IO.Address, Reg, pData, Length); -} - -/** - * @brief TCPP0203 register update function to Bus IO function - * @param handle Component object handle - * @param Reg Target register address to write - * @param pData Target register value to be written - * @param Length Buffer size to be written - * @retval error status - */ -static int32_t TCPP0203_ModifyReg0(TCPP0203_Object_t *pObj, uint8_t Value, uint8_t Mask) -{ - int32_t ret; - uint8_t tmp; - - /* Read current content of ACK register (reflects content of bits set to 1 in Writing register Reg0) */ - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - - /* Update only the area dedicated to Mask */ - tmp &= ~(Mask); - tmp |= (Value & Mask); - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) - Reg0_Expected_Value = tmp; -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - - /* Update value in writing register (reg0) */ - ret += tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, &tmp, 1); - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) - ret += TCPP0203_CheckReg0Reg1(pObj, Reg0_Expected_Value); -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - - return ret; -} - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) -/** - * @brief TCPP0203 register control function between Reg0 and Reg1 value - * @param handle Component object handle - * @param Reg0ExpectedValue Value expected in Reg0 (built after all calls to write functions) - * @retval error status - */ -static int32_t TCPP0203_CheckReg0Reg1(TCPP0203_Object_t *pObj, uint8_t Reg0ExpectedValue) -{ - int32_t ret; - - /* Read current content of ACK register (expected to reflect content of bits set to 1 in Writing register Reg0) */ - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &Reg1_LastRead_Value, 1); - -#ifdef _TRACE - char str[12]; - sprintf(str, "Exp0_0x%02x", Reg0ExpectedValue); - USBPD_TRACE_Add(USBPD_TRACE_DEBUG, 0U, 0U, (uint8_t *)str, sizeof(str) - 1U); - sprintf(str, "Reg1_0x%02x", Reg1_LastRead_Value); - USBPD_TRACE_Add(USBPD_TRACE_DEBUG, 0U, 0U, (uint8_t *)str, sizeof(str) - 1U); -#endif /* _TRACE */ - - /* Control if Reg1 value is same as Reg0 expected one */ - if (Reg1_LastRead_Value != Reg0ExpectedValue) - { - while (1); - } - - return ret; -} -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h deleted file mode 100644 index 271b534fc..000000000 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203.h +++ /dev/null @@ -1,353 +0,0 @@ -/** - ****************************************************************************** - * @file tcpp0203.h - * @author MCD Application Team - * @brief This file contains all the functions prototypes for the - * tcpp0203.c driver. - ****************************************************************************** - * @attention - * - * Copyright (c) 2021 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef TCPP0203_H -#define TCPP0203_H - -/* Includes ------------------------------------------------------------------*/ -#include "tcpp0203_reg.h" -#include - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup Component - * @{ - */ - -/** @addtogroup TCPP0203 - * @{ - */ - -/* Exported types ------------------------------------------------------------*/ - -/** @defgroup TCPP0203_Exported_Types TCPP0203 Exported Types - * @{ - */ -typedef int32_t (*TCPP0203_Init_Func)(void); -typedef int32_t (*TCPP0203_DeInit_Func)(void); -typedef int32_t (*TCPP0203_GetTick_Func)(void); -typedef int32_t (*TCPP0203_WriteReg_Func)(uint16_t, uint16_t, uint8_t *, uint16_t); -typedef int32_t (*TCPP0203_ReadReg_Func)(uint16_t, uint16_t, uint8_t *, uint16_t); - -typedef struct -{ - TCPP0203_Init_Func Init; - TCPP0203_DeInit_Func DeInit; - uint16_t Address; - TCPP0203_WriteReg_Func WriteReg; - TCPP0203_ReadReg_Func ReadReg; - TCPP0203_GetTick_Func GetTick; -} TCPP0203_IO_t; - - -typedef struct -{ - TCPP0203_IO_t IO; - TCPP0203_ctx_t Ctx; - uint8_t IsInitialized; -} TCPP0203_Object_t; - -typedef struct -{ - int32_t (*Init)(TCPP0203_Object_t *); - int32_t (*DeInit)(TCPP0203_Object_t *); - int32_t (*Reset)(TCPP0203_Object_t *); - int32_t (*SetVConnSwitch)(TCPP0203_Object_t *, uint8_t); - int32_t (*SetGateDriverProvider)(TCPP0203_Object_t *, uint8_t); - int32_t (*SetGateDriverConsumer)(TCPP0203_Object_t *, uint8_t); - int32_t (*SetPowerMode)(TCPP0203_Object_t *, uint8_t); - int32_t (*SetVBusDischarge)(TCPP0203_Object_t *, uint8_t); - int32_t (*SetVConnDischarge)(TCPP0203_Object_t *, uint8_t); - int32_t (*GetVConnSwitchAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetGateDriverProviderAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetGateDriverConsumerAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetPowerModeAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetVBusDischargeAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetVConnDischargeAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetOCPVConnFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetOCPVBusFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetOVPVBusFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetOVPCCFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetOTPFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetVBusOkFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*ReadTCPPType)(TCPP0203_Object_t *, uint8_t *); - int32_t (*ReadVCONNPower)(TCPP0203_Object_t *, uint8_t *); - int32_t (*WriteCtrlRegister)(TCPP0203_Object_t *, uint8_t *); - int32_t (*ReadAckRegister)(TCPP0203_Object_t *, uint8_t *); - int32_t (*ReadFlagRegister)(TCPP0203_Object_t *, uint8_t *); -} TCPP0203_Drv_t; - -/** - * @} - */ - -/** @defgroup TCPP0203_Exported_Constants TCPP0203 Exported Constants - * @{ - */ -/** - * @brief TCPP0203 Driver Response codes - */ -#define TCPP0203_OK (0) -#define TCPP0203_ERROR (-1) - -/** - * @brief TCPP0203 possible I2C Addresses - */ -#define TCPP0203_I2C_ADDRESS_X68 (0x68U) -#define TCPP0203_I2C_ADDRESS_X6A (0x6AU) - -/** - * @brief TCPP0203 Reg0 Reset Value - */ -#define TCPP0203_REG0_RST_VALUE TCPP0203_GD_CONSUMER_SWITCH_CLOSED - -/** - * @brief TCPP0203 VCONN Switch - */ -#define TCPP0203_VCONN_SWITCH_POS (0U) -#define TCPP0203_VCONN_SWITCH_MSK (0x03U << TCPP0203_VCONN_SWITCH_POS) -#define TCPP0203_VCONN_SWITCH_OPEN (0x00U) -#define TCPP0203_VCONN_SWITCH_CC1 (0x01U << TCPP0203_VCONN_SWITCH_POS) -#define TCPP0203_VCONN_SWITCH_CC2 (0x02U << TCPP0203_VCONN_SWITCH_POS) - -/** - * @brief TCPP0203 Gate Driver Provider values - */ -#define TCPP0203_GD_PROVIDER_SWITCH_POS (2U) -#define TCPP0203_GD_PROVIDER_SWITCH_MSK (0x01U << TCPP0203_GD_PROVIDER_SWITCH_POS) -#define TCPP0203_GD_PROVIDER_SWITCH_OPEN (0x00U) -#define TCPP0203_GD_PROVIDER_SWITCH_CLOSED (TCPP0203_GD_PROVIDER_SWITCH_MSK) - -/** - * @brief TCPP0203 Gate Driver Consumer values - */ -#define TCPP0203_GD_CONSUMER_SWITCH_POS (3U) -#define TCPP0203_GD_CONSUMER_SWITCH_MSK (0x01U << TCPP0203_GD_CONSUMER_SWITCH_POS) -#define TCPP0203_GD_CONSUMER_SWITCH_CLOSED (0x00U) -#define TCPP0203_GD_CONSUMER_SWITCH_OPEN (TCPP0203_GD_CONSUMER_SWITCH_MSK) - -/** - * @brief TCPP0203 Power Mode values - */ -#define TCPP0203_POWER_MODE_POS (4U) -#define TCPP0203_POWER_MODE_MSK (0x03U << TCPP0203_POWER_MODE_POS) -#define TCPP0203_POWER_MODE_HIBERNATE (0x00U) -#define TCPP0203_POWER_MODE_LOWPOWER (0x02U << TCPP0203_POWER_MODE_POS) -#define TCPP0203_POWER_MODE_NORMAL (0x01U << TCPP0203_POWER_MODE_POS) - -/** - * @brief TCPP0203 VBUS Discharge management - */ -#define TCPP0203_VBUS_DISCHARGE_POS (6U) -#define TCPP0203_VBUS_DISCHARGE_MSK (0x01U << TCPP0203_VBUS_DISCHARGE_POS) -#define TCPP0203_VBUS_DISCHARGE_OFF (0x00U) -#define TCPP0203_VBUS_DISCHARGE_ON (TCPP0203_VBUS_DISCHARGE_MSK) - -/** - * @brief TCPP0203 VConn Discharge management - */ -#define TCPP0203_VCONN_DISCHARGE_POS (7U) -#define TCPP0203_VCONN_DISCHARGE_MSK (0x01U << TCPP0203_VCONN_DISCHARGE_POS) -#define TCPP0203_VCONN_DISCHARGE_OFF (0x00U) -#define TCPP0203_VCONN_DISCHARGE_ON (TCPP0203_VCONN_DISCHARGE_MSK) - -/** - * @brief TCPP0203 VCONN Switch Acknowledge - */ -#define TCPP0203_VCONN_SWITCH_ACK_POS (0U) -#define TCPP0203_VCONN_SWITCH_ACK_MSK (0x03U << TCPP0203_VCONN_SWITCH_ACK_POS) -#define TCPP0203_VCONN_SWITCH_ACK_OPEN (0x00U) -#define TCPP0203_VCONN_SWITCH_ACK_CC1 (0x02U << TCPP0203_VCONN_SWITCH_ACK_POS) -#define TCPP0203_VCONN_SWITCH_ACK_CC2 (0x01U << TCPP0203_VCONN_SWITCH_ACK_POS) - -/** - * @brief TCPP0203 Gate Driver Provider Acknowledge - */ -#define TCPP0203_GD_PROVIDER_SWITCH_ACK_POS (2U) -#define TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK (0x01U << TCPP0203_GD_PROVIDER_SWITCH_ACK_POS) -#define TCPP0203_GD_PROVIDER_SWITCH_ACK_OPEN (0x00U) -#define TCPP0203_GD_PROVIDER_SWITCH_ACK_CLOSED (TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK) - -/** - * @brief TCPP0203 Gate Driver Consumer Acknowledge - */ -#define TCPP0203_GD_CONSUMER_SWITCH_ACK_POS (3U) -#define TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK (0x01U << TCPP0203_GD_CONSUMER_SWITCH_ACK_POS) -#define TCPP0203_GD_CONSUMER_SWITCH_ACK_CLOSED (0x00U) -#define TCPP0203_GD_CONSUMER_SWITCH_ACK_OPEN (TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK) - -/** - * @brief TCPP0203 Power Mode Acknowledge - */ -#define TCPP0203_POWER_MODE_ACK_POS (4U) -#define TCPP0203_POWER_MODE_ACK_MSK (0x03U << TCPP0203_POWER_MODE_ACK_POS) -#define TCPP0203_POWER_MODE_ACK_HIBERNATE (0x00U) -#define TCPP0203_POWER_MODE_ACK_LOWPOWER (0x01U << TCPP0203_POWER_MODE_ACK_POS) -#define TCPP0203_POWER_MODE_ACK_NORMAL (0x02U << TCPP0203_POWER_MODE_ACK_POS) - -/** - * @brief TCPP0203 VBUS Discharge Acknowledge - */ -#define TCPP0203_VBUS_DISCHARGE_ACK_POS (6U) -#define TCPP0203_VBUS_DISCHARGE_ACK_MSK (0x01U << TCPP0203_VBUS_DISCHARGE_ACK_POS) -#define TCPP0203_VBUS_DISCHARGE_ACK_OFF (0x00U) -#define TCPP0203_VBUS_DISCHARGE_ACK_ON (TCPP0203_VBUS_DISCHARGE_ACK_MSK) - -/** - * @brief TCPP0203 VConn Discharge Acknowledge - */ -#define TCPP0203_VCONN_DISCHARGE_ACK_POS (7U) -#define TCPP0203_VCONN_DISCHARGE_ACK_MSK (0x01U << TCPP0203_VCONN_DISCHARGE_ACK_POS) -#define TCPP0203_VCONN_DISCHARGE_ACK_OFF (0x00U) -#define TCPP0203_VCONN_DISCHARGE_ACK_ON (TCPP0203_VCONN_DISCHARGE_ACK_MSK) - -/** - * @brief TCPP0203 OCP Vconn Flag management - */ -#define TCPP0203_FLAG_OCP_VCONN_POS (0U) -#define TCPP0203_FLAG_OCP_VCONN_MSK (0x01U << TCPP0203_FLAG_OCP_VCONN_POS) -#define TCPP0203_FLAG_OCP_VCONN_SET (TCPP0203_FLAG_OCP_VCONN_MSK) -#define TCPP0203_FLAG_OCP_VCONN_RESET (0x00U) - -/** - * @brief TCPP0203 OCP VBUS Flag management - */ -#define TCPP0203_FLAG_OCP_VBUS_POS (1U) -#define TCPP0203_FLAG_OCP_VBUS_MSK (0x01U << TCPP0203_FLAG_OCP_VBUS_POS) -#define TCPP0203_FLAG_OCP_VBUS_SET (TCPP0203_FLAG_OCP_VBUS_MSK) -#define TCPP0203_FLAG_OCP_VBUS_RESET (0x00U) - -/** - * @brief TCPP0203 OVP VBUS Flag management - */ -#define TCPP0203_FLAG_OVP_VBUS_POS (2U) -#define TCPP0203_FLAG_OVP_VBUS_MSK (0x01U << TCPP0203_FLAG_OVP_VBUS_POS) -#define TCPP0203_FLAG_OVP_VBUS_SET (TCPP0203_FLAG_OVP_VBUS_MSK) -#define TCPP0203_FLAG_OVP_VBUS_RESET (0x00U) - -/** - * @brief TCPP0203 OVP CC Flag management - */ -#define TCPP0203_FLAG_OVP_CC_POS (3U) -#define TCPP0203_FLAG_OVP_CC_MSK (0x01U << TCPP0203_FLAG_OVP_CC_POS) -#define TCPP0203_FLAG_OVP_CC_SET (TCPP0203_FLAG_OVP_CC_MSK) -#define TCPP0203_FLAG_OVP_CC_RESET (0x00U) - -/** - * @brief TCPP0203 OTP Flag management - */ -#define TCPP0203_FLAG_OTP_POS (4U) -#define TCPP0203_FLAG_OTP_MSK (0x01U << TCPP0203_FLAG_OTP_POS) -#define TCPP0203_FLAG_OTP_SET (TCPP0203_FLAG_OTP_MSK) -#define TCPP0203_FLAG_OTP_RESET (0x00U) - -/** - * @brief TCPP0203 VBUS OK Flag management - */ -#define TCPP0203_FLAG_VBUS_OK_POS (5U) -#define TCPP0203_FLAG_VBUS_OK_MSK (0x01U << TCPP0203_FLAG_VBUS_OK_POS) -#define TCPP0203_FLAG_VBUS_OK_SET (TCPP0203_FLAG_VBUS_OK_MSK) -#define TCPP0203_FLAG_VBUS_OK_RESET (0x00U) - -/** - * @brief TCPP0203 VConn Power - */ -#define TCPP0203_FLAG_VCONN_PWR_POS (6U) -#define TCPP0203_FLAG_VCONN_PWR_MSK (0x01U << TCPP0203_FLAG_VCONN_PWR_POS) -#define TCPP0203_FLAG_VCONN_PWR_1W (TCPP0203_FLAG_VCONN_PWR_MSK) -#define TCPP0203_FLAG_VCONN_PWR_0_1W (0x00U) - -/** - * @brief TCPP0203 Device Type - */ -#define TCPP0203_DEVICE_TYPE_POS (7U) -#define TCPP0203_DEVICE_TYPE_MSK (0x01U << TCPP0203_DEVICE_TYPE_POS) -#define TCPP0203_DEVICE_TYPE_02 (TCPP0203_DEVICE_TYPE_MSK) -#define TCPP0203_DEVICE_TYPE_03 (0x00U) - -/** - * @} - */ - -/** @defgroup TCPP0203_Exported_Macros TCPP0203 Exported Macros - * @{ - */ -/** - * @} - */ - -/** @defgroup TCPP0203_Exported_Functions TCPP0203 Exported Functions - * @{ - */ - -/*------------------------------------------------------------------------------ - TCPP02/03 Type-C port protection functions -------------------------------------------------------------------------------*/ -/* High Layer codec functions */ -int32_t TCPP0203_RegisterBusIO(TCPP0203_Object_t *pObj, TCPP0203_IO_t *pIO); -int32_t TCPP0203_Init(TCPP0203_Object_t *pObj); -int32_t TCPP0203_DeInit(TCPP0203_Object_t *pObj); -int32_t TCPP0203_Reset(TCPP0203_Object_t *pObj); -int32_t TCPP0203_SetVConnSwitch(TCPP0203_Object_t *pObj, uint8_t VConnSwitch); -int32_t TCPP0203_SetGateDriverProvider(TCPP0203_Object_t *pObj, uint8_t GateDriverProvider); -int32_t TCPP0203_SetGateDriverConsumer(TCPP0203_Object_t *pObj, uint8_t GateDriverConsumer); -int32_t TCPP0203_SetPowerMode(TCPP0203_Object_t *pObj, uint8_t PowerMode); -int32_t TCPP0203_SetVBusDischarge(TCPP0203_Object_t *pObj, uint8_t VBusDischarge); -int32_t TCPP0203_SetVConnDischarge(TCPP0203_Object_t *pObj, uint8_t VConnDischarge); -int32_t TCPP0203_GetVConnSwitchAck(TCPP0203_Object_t *pObj, uint8_t *pVConnSwitchAck); -int32_t TCPP0203_GetGateDriverProviderAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverProviderAck); -int32_t TCPP0203_GetGateDriverConsumerAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverConsumerAck); -int32_t TCPP0203_GetPowerModeAck(TCPP0203_Object_t *pObj, uint8_t *pPowerModeAck); -int32_t TCPP0203_GetVBusDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVBusDischargeAck); -int32_t TCPP0203_GetVConnDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVConnDischargeAck); -int32_t TCPP0203_GetOCPVConnFlag(TCPP0203_Object_t *pObj, uint8_t *pOCPVConnFlag); -int32_t TCPP0203_GetOCPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pGetOCPVBusFlag); -int32_t TCPP0203_GetOVPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPVBusFlag); -int32_t TCPP0203_GetOVPCCFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPCCFlag); -int32_t TCPP0203_GetOTPFlag(TCPP0203_Object_t *pObj, uint8_t *pOTPFlag); -int32_t TCPP0203_GetVBusOkFlag(TCPP0203_Object_t *pObj, uint8_t *pVBusOkFlag); -int32_t TCPP0203_ReadTCPPType(TCPP0203_Object_t *pObj, uint8_t *pTCPPType); -int32_t TCPP0203_ReadVCONNPower(TCPP0203_Object_t *pObj, uint8_t *pVCONNPower); -int32_t TCPP0203_WriteCtrlRegister(TCPP0203_Object_t *pObj, uint8_t *pCtrlRegister); -int32_t TCPP0203_ReadAckRegister(TCPP0203_Object_t *pObj, uint8_t *pAckRegister); -int32_t TCPP0203_ReadFlagRegister(TCPP0203_Object_t *pObj, uint8_t *pFlagRegister); - -/** - * @} - */ - -/* TCPP02/03 Type-C port protection driver structure */ -extern TCPP0203_Drv_t TCPP0203_Driver; - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#endif /* TCPP0203_H */ diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c deleted file mode 100644 index 8025fa85e..000000000 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.c +++ /dev/null @@ -1,73 +0,0 @@ -/** - ****************************************************************************** - * @file tcpp0203_reg.c - * @author MCD Application Team - * @brief This file provides unitary register function to control the TCPP02-03 - * Type-C port protection driver. - ****************************************************************************** - * @attention - * - * Copyright (c) 2021 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "tcpp0203_reg.h" - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup Components - * @{ - */ - -/** @addtogroup TCPP0203 - * @brief This file provides a set of functions needed to drive the - * TCPP02/03 Type-C port protection codec. - * @{ - */ - -/************** Generic Function *******************/ -/******************************************************************************* - * Function Name : tcpp0203_read_reg - * Description : Generic Reading function. It must be fulfilled with either - * I2C or SPI reading functions - * Input : Register Address, length of buffer - * Output : data Read - *******************************************************************************/ -int32_t tcpp0203_read_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length) -{ - return ctx->ReadReg(ctx->handle, reg, data, length); -} - -/******************************************************************************* - * Function Name : tcpp0203_write_reg - * Description : Generic Writing function. It must be fulfilled with either - * I2C or SPI writing function - * Input : Register Address, data to be written, length of buffer - * Output : None - *******************************************************************************/ -int32_t tcpp0203_write_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length) -{ - return ctx->WriteReg(ctx->handle, reg, data, length); -} - -/******************************************************************************/ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h deleted file mode 100644 index 92420e1fe..000000000 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/tcpp0203/tcpp0203_reg.h +++ /dev/null @@ -1,98 +0,0 @@ -/** - ****************************************************************************** - * @file tcpp0203_reg.h - * @author MCD Application Team - * @brief Header of tcpp0203_reg.c - * - ****************************************************************************** - * @attention - * - * Copyright (c) 2021 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef TCPP0203_REG_H -#define TCPP0203_REG_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup Component - * @{ - */ - -/** @addtogroup TCPP0203 - * @{ - */ - - -/** @defgroup TCPP0203_Exported_Constants TCPP0203 Exported Constants - * @{ - */ -/******************************************************************************/ -/****************************** REGISTER MAPPING ******************************/ -/******************************************************************************/ -#define TCPP0203_WRITE_REG 0x00U -#define TCPP0203_PROG_CTRL TCPP0203_WRITE_REG -#define TCPP0203_READ_REG1 0x01U -#define TCPP0203_ACK_REG TCPP0203_READ_REG1 -#define TCPP0203_READ_REG2 0x02U -#define TCPP0203_FLAG_REG TCPP0203_READ_REG2 - -/** - * @} - */ - -/************** Generic Function *******************/ - -typedef int32_t (*TCPP0203_Write_Func)(const void *, uint8_t, uint8_t *, uint8_t); -typedef int32_t (*TCPP0203_Read_Func)(const void *, uint8_t, uint8_t *, uint8_t); - -typedef struct -{ - TCPP0203_Write_Func WriteReg; - TCPP0203_Read_Func ReadReg; - void *handle; -} TCPP0203_ctx_t; - -/******************************************************************************* - * Register : Generic - All - * Address : Generic - All - * Bit Group Name: None - * Permission : W - *******************************************************************************/ -int32_t tcpp0203_write_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length); -int32_t tcpp0203_read_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length); - -#ifdef __cplusplus -} -#endif - -#endif /* TCPP0203_REG_H */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/hw/bsp/stm32h7rs/family.cmake b/hw/bsp/stm32h7rs/family.cmake index 61c3ebaea..e5e98f914 100644 --- a/hw/bsp/stm32h7rs/family.cmake +++ b/hw/bsp/stm32h7rs/family.cmake @@ -5,6 +5,7 @@ set(ST_PREFIX stm32${ST_FAMILY}xx) set(ST_HAL_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver) set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis_device_${ST_FAMILY}) +set(ST_TCPP0203 ${TOP}/hw/mcu/st/stm32-tcpp0203) set(CMSIS_5 ${TOP}/lib/CMSIS_5) # include board specific @@ -86,6 +87,8 @@ function(add_board_target BOARD_TARGET) BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} BOARD_TUH_RHPORT=${RHPORT_HOST} BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} + SEGGER_RTT_SECTION="noncacheable_buffer" + BUFFER_SIZE_UP=0x3000 ) update_board(${BOARD_TARGET}) diff --git a/hw/bsp/stm32h7rs/family.mk b/hw/bsp/stm32h7rs/family.mk index d679b72f1..9970059f8 100644 --- a/hw/bsp/stm32h7rs/family.mk +++ b/hw/bsp/stm32h7rs/family.mk @@ -2,6 +2,7 @@ ST_FAMILY = h7rs ST_PREFIX = stm32${ST_FAMILY}xx ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/${ST_PREFIX}_hal_driver +ST_TCPP0203 = hw/mcu/st/stm32-tcpp0203 UF2_FAMILY_ID = 0x6db66083 @@ -42,6 +43,8 @@ CFLAGS += \ -DBOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} \ -DBOARD_TUH_RHPORT=${RHPORT_HOST} \ -DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} \ + -DSEGGER_RTT_SECTION=\"noncacheable_buffer\" \ + -DBUFFER_SIZE_UP=0x3000 \ # GCC Flags CFLAGS_GCC += \ diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake index 789eb9a2e..e88efefb9 100644 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.cmake @@ -7,13 +7,11 @@ function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC STM32N657xx ) - target_sources(${TARGET} PUBLIC - # BSP - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tcpp0203/tcpp0203.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tcpp0203/tcpp0203_reg.c + ${ST_TCPP0203}/tcpp0203.c + ${ST_TCPP0203}/tcpp0203_reg.c ) target_include_directories(${TARGET} PUBLIC - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/tcpp0203 + ${ST_TCPP0203} ) endfunction() diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk index bfbe5b23c..05717699c 100644 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk +++ b/hw/bsp/stm32n6/boards/stm32n657nucleo/board.mk @@ -10,8 +10,8 @@ flash: flash-stlink PORT = 1 SRC_C += \ - $(BOARD_PATH)/tcpp0203/tcpp0203.c \ - $(BOARD_PATH)/tcpp0203/tcpp0203_reg.c \ + $(ST_TCPP0203)/tcpp0203.c \ + $(ST_TCPP0203)/tcpp0203_reg.c \ INC += \ - $(TOP)/$(BOARD_PATH)/tcpp0203 \ + $(TOP)/$(ST_TCPP0203) \ diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/LICENSE.txt b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/LICENSE.txt deleted file mode 100644 index 1cbbc544a..000000000 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/LICENSE.txt +++ /dev/null @@ -1,6 +0,0 @@ -This software component is provided to you as part of a software package and -applicable license terms are in the Package_license file. If you received this -software component outside of a package or without applicable license terms, -the terms of the BSD-3-Clause license shall apply. -You may obtain a copy of the BSD-3-Clause at: -https://opensource.org/licenses/BSD-3-Clause diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/Release_Notes.html b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/Release_Notes.html deleted file mode 100644 index 6bbba86a4..000000000 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/Release_Notes.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - - Release Notes for TCPP0203 Component Driver - - - - - - -
-
-
-

Release Notes for TCPP0203 Component Driver

-

Copyright © 2020 STMicroelectronics
-

- -
-

Purpose

-

This driver provides a set of functions needed to drive TCPP0203 Type-C Port Protection component

-
-
-

Update History

-
- -
-

Main Changes

-

Maintenance release

-

Contents

- - - - - - - - - - - -
Headline
MISRA Rule-81.13 correction on TCPP0203 component driver files
-

Backward compatibility

-

No compatibility break with previous version

-

Dependencies

-
-
-
- -
-

Main Changes

-

Maintenance release

-

Contents

- - - - - - - - - - - - -
Fixed bugs list
Headline
MISRA corrections on TCPP0203 component driver files
-

Known Limitations

-

Outstanding bugs list : None

-

Requirements not met or planned in a forthcoming release : None

-

Development Toolchains and Compilers

-
    -
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • -
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • -
  • STM32CubeIDE toolchain V1.8.0
  • -
-

Backward compatibility

-

No compatibility break with previous version

-

Dependencies

-
-
-
- -
-

Main Changes

-

Maintenance release

-

Contents

- - - - - - - - - - - - -
Fixed bugs list
Headline
License updates
-

Known Limitations

-

Outstanding bugs list : None

-

Requirements not met or planned in a forthcoming release : None

-

Development Toolchains and Compilers

-
    -
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • -
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • -
  • STM32CubeIDE toolchain V1.6.0
  • -
-

Backward compatibility

-

No compatibility break with previous version

-

Dependencies

-
-
-
- -
-

Main Changes

-

Maintenance release

-

Contents

- - - - - - - - - - - - -
Fixed bugs list
Headline
CodeSpell correction on TCPP0203 component driver files
-

Known Limitations

-

Outstanding bugs list : None

-

Requirements not met or planned in a forthcoming release : None

-

Development Toolchains and Compilers

-
    -
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • -
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • -
  • STM32CubeIDE toolchain V1.5.0
  • -
-

Backward compatibility

-

No compatibility break with previous version

-

Dependencies

-
-
-
- -
-

Main Changes

-

Maintenance release

-

Contents

- - - - - - - - - - - - -
Fixed bugs list
Headline
MCUAstyle correction on TCPP0203 component driver files
-

Known Limitations

-

Outstanding bugs list : None

-

Requirements not met or planned in a forthcoming release : None

-

Development Toolchains and Compilers

-
    -
  • IAR Embedded Workbench for ARM (EWARM) toolchain V8.32.3
  • -
  • RealView Microcontroller Development Kit (MDK-ARM) toolchain V5.27.1
  • -
  • STM32CubeIDE toolchain V1.5.0
  • -
-

Backward compatibility

-

No compatibility break with previous version

-

Dependencies

-
-
-
- -
-

Main Changes

-
    -
  • First official release of TCPP0203 Type-C port Protection Component drivers
  • -
-
-
-
-
-
-

For complete documentation on STM32,visit: [www.st.com/stm32]

-This release note uses up to date web standards and, for this reason, should not be opened with Internet Explorer but preferably with popular browsers such as Google Chrome, Mozilla Firefox, Opera or Microsoft Edge. -
- - diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/favicon.png b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/favicon.png deleted file mode 100644 index 06713eec4974e141c6e9b4156d34e61e89f282ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4126 zcmV+(5aI8MP)ZIGU@QfPy~$kHP}Vz9c$a)g>fT6hB^OaK4>c|MGS0000HbW%=J|NsC0|NsC0 z|NsC0|NsC0041%NVgLXD!bwCyRCwCllie1CAP9sJ&9ooo{hxLjw5@YC+xxf~%TE}{ zNd5%935b--eKa7{Q8)vZ;eI6pGFH>rL)887WOA={e(b_&0g-g6to#Hm2B3vqWV>1u z@z7*I(bdWdx-Y=OT@|og)oZEgAbc7ep|Gf{$7j1Oa#T&r4>0xv(+}tR_4biWa z1Q-BfcsgeLIJPbT0000rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000F^NklQWRUVq~pvFslpiNq83Yr*1(ELa!!kppKfxQKEkPzz^I>0W)!71xam z(B64`)5a~kHf9SBOp*Wvo{xA*e4|Kv3g6TCo+fF8q^C$|g>#NlXyY$%lmkmCh$x1Z zFbJ_hiDG`37w>KPVB83d7E3>R@-M9$`|}|QFF}1qSk!nanPdVd3K38edo3y+D*=Uo zfOWCwj(F@GSjPG&B<0O;H!Zm0g>eDeK09{b@xB};mEy; z;Gp5H_Cr65qKM1uYIu6x&16!Ei=BHfJLe)1IUnFqc6d#D=ZVQmV9C73vy1=x$SK;s z=*CYZP+Ei1D5Vjl#u88v5dv#jId?iu)8mM}{mD`GcMXtAC5ap?ZoKr&iYuqTKHe$t zTR%R$ZZwxec?l+0r_LIVbe-mzH+D0*ZYsu4BE~~JA2A+AD?BAArO=g8ZfvXtU~o9c zZ(Bd-RFK5jh*DvM1v6^41HB@0K0qn7E8E&Xz1mk6hvmx?*|WB_H!dcO;5R$=<4b~s z5zr3N4zxlkMKOrDeny(PGpEM6^hGyc7lhg>MWtM!af*pn%&q_PxI(n^(-Zd{ICPAp z(WE@Zz5|EZyt{MEDy&l5$Cba^zU!9k&;Vs7lk$@o02LOwb#e2{#3%Cn2>kQF(RKUU z+tW!;FT0@d+TX^L;>@3RytlTP&ts$pqA}TwENBlg9?$-D zF9Sn4URZx8)hVBw<~NY=h3=so7{jEhG%Zc_0QBSvY~K4BS|W5MAem5XSb6m}VDN$f zy+b3n9qjIJoHM5pqYa`IPH9AIoM=!AE1Er>r|3E}#Jq-S)cTrfD&TZjAuN@+V}3mi zlhOce+q<8>Y?i93G=*Z3Web`ri!Q%p%LR*(bB?;|)B`&=J&ab0Z(UKpbzyZV5o*#& z0FLzzaI$v*-#WB)+`n>BoJ*1AwU0XSu;@w&Hu1WYXVR#!8itC%68CzMeiXhL#`9W$9J30NB-Wg!ex`hBlg9F5u@&o4>hd`TWPv z{r{JbyvQGZzbyvPS}zAifbhF49z~X|@9v|!=No>qsF|P~vf=g>7#%0yk<U?Ha8*Z4HW>#8w>z$A3 z>^uQlk;$a-6CQ(uc@RM)Cbss!xuPVl2@c1u-5tEUw}U8OfP_J+QYhfu$B<0Cj3xm7 c?*aZZ00ulYFs-m=@&Et;07*qoM6N<$f~=14i~s-t diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/mini-st_2020.css b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/mini-st_2020.css deleted file mode 100644 index dd19969d1..000000000 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/mini-st_2020.css +++ /dev/null @@ -1,1703 +0,0 @@ -@charset "UTF-8"; -/* - Flavor name: Custom (mini-custom) - Generated online - https://minicss.org/flavors - mini.css version: v3.0.1 -*/ -/* - Browsers resets and base typography. -*/ -/* Core module CSS variable definitions */ -:root { - --fore-color: #03234b; - --secondary-fore-color: #03234b; - --back-color: #ffffff; - --secondary-back-color: #ffffff; - --blockquote-color: #e6007e; - --pre-color: #e6007e; - --border-color: #3cb4e6; - --secondary-border-color: #3cb4e6; - --heading-ratio: 1.2; - --universal-margin: 0.5rem; - --universal-padding: 0.25rem; - --universal-border-radius: 0.075rem; - --background-margin: 1.5%; - --a-link-color: #3cb4e6; - --a-visited-color: #8c0078; } - -html { - font-size: 13.5px; } - -a, b, del, em, i, ins, q, span, strong, u { - font-size: 1em; } - -html, * { - font-family: -apple-system, BlinkMacSystemFont, Helvetica, arial, sans-serif; - line-height: 1.25; - -webkit-text-size-adjust: 100%; } - -* { - font-size: 1rem; } - -body { - margin: 0; - color: var(--fore-color); - @background: var(--back-color); - background: var(--back-color) linear-gradient(#ffd200, #ffd200) repeat-y left top; - background-size: var(--background-margin); - } - -details { - display: block; } - -summary { - display: list-item; } - -abbr[title] { - border-bottom: none; - text-decoration: underline dotted; } - -input { - overflow: visible; } - -img { - max-width: 100%; - height: auto; } - -h1, h2, h3, h4, h5, h6 { - line-height: 1.25; - margin: calc(1.5 * var(--universal-margin)) var(--universal-margin); - font-weight: 400; } - h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { - color: var(--secondary-fore-color); - display: block; - margin-top: -0.25rem; } - -h1 { - font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio)); } - -h2 { - font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) ); - border-style: none none solid none ; - border-width: thin; - border-color: var(--border-color); } -h3 { - font-size: calc(1rem * var(--heading-ratio) ); } - -h4 { - font-size: calc(1rem * var(--heading-ratio)); } - -h5 { - font-size: 1rem; } - -h6 { - font-size: calc(1rem / var(--heading-ratio)); } - -p { - margin: var(--universal-margin); } - -ol, ul { - margin: var(--universal-margin); - padding-left: calc(3 * var(--universal-margin)); } - -b, strong { - font-weight: 700; } - -hr { - box-sizing: content-box; - border: 0; - line-height: 1.25em; - margin: var(--universal-margin); - height: 0.0714285714rem; - background: linear-gradient(to right, transparent, var(--border-color) 20%, var(--border-color) 80%, transparent); } - -blockquote { - display: block; - position: relative; - font-style: italic; - color: var(--secondary-fore-color); - margin: var(--universal-margin); - padding: calc(3 * var(--universal-padding)); - border: 0.0714285714rem solid var(--secondary-border-color); - border-left: 0.3rem solid var(--blockquote-color); - border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } - blockquote:before { - position: absolute; - top: calc(0rem - var(--universal-padding)); - left: 0; - font-family: sans-serif; - font-size: 2rem; - font-weight: 800; - content: "\201c"; - color: var(--blockquote-color); } - blockquote[cite]:after { - font-style: normal; - font-size: 0.75em; - font-weight: 700; - content: "\a— " attr(cite); - white-space: pre; } - -code, kbd, pre, samp { - font-family: Menlo, Consolas, monospace; - font-size: 0.85em; } - -code { - background: var(--secondary-back-color); - border-radius: var(--universal-border-radius); - padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } - -kbd { - background: var(--fore-color); - color: var(--back-color); - border-radius: var(--universal-border-radius); - padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } - -pre { - overflow: auto; - background: var(--secondary-back-color); - padding: calc(1.5 * var(--universal-padding)); - margin: var(--universal-margin); - border: 0.0714285714rem solid var(--secondary-border-color); - border-left: 0.2857142857rem solid var(--pre-color); - border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } - -sup, sub, code, kbd { - line-height: 0; - position: relative; - vertical-align: baseline; } - -small, sup, sub, figcaption { - font-size: 0.75em; } - -sup { - top: -0.5em; } - -sub { - bottom: -0.25em; } - -figure { - margin: var(--universal-margin); } - -figcaption { - color: var(--secondary-fore-color); } - -a { - text-decoration: none; } - a:link { - color: var(--a-link-color); } - a:visited { - color: var(--a-visited-color); } - a:hover, a:focus { - text-decoration: underline; } - -/* - Definitions for the grid system, cards and containers. -*/ -.container { - margin: 0 auto; - padding: 0 calc(1.5 * var(--universal-padding)); } - -.row { - box-sizing: border-box; - display: flex; - flex: 0 1 auto; - flex-flow: row wrap; - margin: 0 0 0 var(--background-margin); } - -.col-sm, -[class^='col-sm-'], -[class^='col-sm-offset-'], -.row[class*='cols-sm-'] > * { - box-sizing: border-box; - flex: 0 0 auto; - padding: 0 calc(var(--universal-padding) / 2); } - -.col-sm, -.row.cols-sm > * { - max-width: 100%; - flex-grow: 1; - flex-basis: 0; } - -.col-sm-1, -.row.cols-sm-1 > * { - max-width: 8.3333333333%; - flex-basis: 8.3333333333%; } - -.col-sm-offset-0 { - margin-left: 0; } - -.col-sm-2, -.row.cols-sm-2 > * { - max-width: 16.6666666667%; - flex-basis: 16.6666666667%; } - -.col-sm-offset-1 { - margin-left: 8.3333333333%; } - -.col-sm-3, -.row.cols-sm-3 > * { - max-width: 25%; - flex-basis: 25%; } - -.col-sm-offset-2 { - margin-left: 16.6666666667%; } - -.col-sm-4, -.row.cols-sm-4 > * { - max-width: 33.3333333333%; - flex-basis: 33.3333333333%; } - -.col-sm-offset-3 { - margin-left: 25%; } - -.col-sm-5, -.row.cols-sm-5 > * { - max-width: 41.6666666667%; - flex-basis: 41.6666666667%; } - -.col-sm-offset-4 { - margin-left: 33.3333333333%; } - -.col-sm-6, -.row.cols-sm-6 > * { - max-width: 50%; - flex-basis: 50%; } - -.col-sm-offset-5 { - margin-left: 41.6666666667%; } - -.col-sm-7, -.row.cols-sm-7 > * { - max-width: 58.3333333333%; - flex-basis: 58.3333333333%; } - -.col-sm-offset-6 { - margin-left: 50%; } - -.col-sm-8, -.row.cols-sm-8 > * { - max-width: 66.6666666667%; - flex-basis: 66.6666666667%; } - -.col-sm-offset-7 { - margin-left: 58.3333333333%; } - -.col-sm-9, -.row.cols-sm-9 > * { - max-width: 75%; - flex-basis: 75%; } - -.col-sm-offset-8 { - margin-left: 66.6666666667%; } - -.col-sm-10, -.row.cols-sm-10 > * { - max-width: 83.3333333333%; - flex-basis: 83.3333333333%; } - -.col-sm-offset-9 { - margin-left: 75%; } - -.col-sm-11, -.row.cols-sm-11 > * { - max-width: 91.6666666667%; - flex-basis: 91.6666666667%; } - -.col-sm-offset-10 { - margin-left: 83.3333333333%; } - -.col-sm-12, -.row.cols-sm-12 > * { - max-width: 100%; - flex-basis: 100%; } - -.col-sm-offset-11 { - margin-left: 91.6666666667%; } - -.col-sm-normal { - order: initial; } - -.col-sm-first { - order: -999; } - -.col-sm-last { - order: 999; } - -@media screen and (min-width: 500px) { - .col-md, - [class^='col-md-'], - [class^='col-md-offset-'], - .row[class*='cols-md-'] > * { - box-sizing: border-box; - flex: 0 0 auto; - padding: 0 calc(var(--universal-padding) / 2); } - - .col-md, - .row.cols-md > * { - max-width: 100%; - flex-grow: 1; - flex-basis: 0; } - - .col-md-1, - .row.cols-md-1 > * { - max-width: 8.3333333333%; - flex-basis: 8.3333333333%; } - - .col-md-offset-0 { - margin-left: 0; } - - .col-md-2, - .row.cols-md-2 > * { - max-width: 16.6666666667%; - flex-basis: 16.6666666667%; } - - .col-md-offset-1 { - margin-left: 8.3333333333%; } - - .col-md-3, - .row.cols-md-3 > * { - max-width: 25%; - flex-basis: 25%; } - - .col-md-offset-2 { - margin-left: 16.6666666667%; } - - .col-md-4, - .row.cols-md-4 > * { - max-width: 33.3333333333%; - flex-basis: 33.3333333333%; } - - .col-md-offset-3 { - margin-left: 25%; } - - .col-md-5, - .row.cols-md-5 > * { - max-width: 41.6666666667%; - flex-basis: 41.6666666667%; } - - .col-md-offset-4 { - margin-left: 33.3333333333%; } - - .col-md-6, - .row.cols-md-6 > * { - max-width: 50%; - flex-basis: 50%; } - - .col-md-offset-5 { - margin-left: 41.6666666667%; } - - .col-md-7, - .row.cols-md-7 > * { - max-width: 58.3333333333%; - flex-basis: 58.3333333333%; } - - .col-md-offset-6 { - margin-left: 50%; } - - .col-md-8, - .row.cols-md-8 > * { - max-width: 66.6666666667%; - flex-basis: 66.6666666667%; } - - .col-md-offset-7 { - margin-left: 58.3333333333%; } - - .col-md-9, - .row.cols-md-9 > * { - max-width: 75%; - flex-basis: 75%; } - - .col-md-offset-8 { - margin-left: 66.6666666667%; } - - .col-md-10, - .row.cols-md-10 > * { - max-width: 83.3333333333%; - flex-basis: 83.3333333333%; } - - .col-md-offset-9 { - margin-left: 75%; } - - .col-md-11, - .row.cols-md-11 > * { - max-width: 91.6666666667%; - flex-basis: 91.6666666667%; } - - .col-md-offset-10 { - margin-left: 83.3333333333%; } - - .col-md-12, - .row.cols-md-12 > * { - max-width: 100%; - flex-basis: 100%; } - - .col-md-offset-11 { - margin-left: 91.6666666667%; } - - .col-md-normal { - order: initial; } - - .col-md-first { - order: -999; } - - .col-md-last { - order: 999; } } -@media screen and (min-width: 1280px) { - .col-lg, - [class^='col-lg-'], - [class^='col-lg-offset-'], - .row[class*='cols-lg-'] > * { - box-sizing: border-box; - flex: 0 0 auto; - padding: 0 calc(var(--universal-padding) / 2); } - - .col-lg, - .row.cols-lg > * { - max-width: 100%; - flex-grow: 1; - flex-basis: 0; } - - .col-lg-1, - .row.cols-lg-1 > * { - max-width: 8.3333333333%; - flex-basis: 8.3333333333%; } - - .col-lg-offset-0 { - margin-left: 0; } - - .col-lg-2, - .row.cols-lg-2 > * { - max-width: 16.6666666667%; - flex-basis: 16.6666666667%; } - - .col-lg-offset-1 { - margin-left: 8.3333333333%; } - - .col-lg-3, - .row.cols-lg-3 > * { - max-width: 25%; - flex-basis: 25%; } - - .col-lg-offset-2 { - margin-left: 16.6666666667%; } - - .col-lg-4, - .row.cols-lg-4 > * { - max-width: 33.3333333333%; - flex-basis: 33.3333333333%; } - - .col-lg-offset-3 { - margin-left: 25%; } - - .col-lg-5, - .row.cols-lg-5 > * { - max-width: 41.6666666667%; - flex-basis: 41.6666666667%; } - - .col-lg-offset-4 { - margin-left: 33.3333333333%; } - - .col-lg-6, - .row.cols-lg-6 > * { - max-width: 50%; - flex-basis: 50%; } - - .col-lg-offset-5 { - margin-left: 41.6666666667%; } - - .col-lg-7, - .row.cols-lg-7 > * { - max-width: 58.3333333333%; - flex-basis: 58.3333333333%; } - - .col-lg-offset-6 { - margin-left: 50%; } - - .col-lg-8, - .row.cols-lg-8 > * { - max-width: 66.6666666667%; - flex-basis: 66.6666666667%; } - - .col-lg-offset-7 { - margin-left: 58.3333333333%; } - - .col-lg-9, - .row.cols-lg-9 > * { - max-width: 75%; - flex-basis: 75%; } - - .col-lg-offset-8 { - margin-left: 66.6666666667%; } - - .col-lg-10, - .row.cols-lg-10 > * { - max-width: 83.3333333333%; - flex-basis: 83.3333333333%; } - - .col-lg-offset-9 { - margin-left: 75%; } - - .col-lg-11, - .row.cols-lg-11 > * { - max-width: 91.6666666667%; - flex-basis: 91.6666666667%; } - - .col-lg-offset-10 { - margin-left: 83.3333333333%; } - - .col-lg-12, - .row.cols-lg-12 > * { - max-width: 100%; - flex-basis: 100%; } - - .col-lg-offset-11 { - margin-left: 91.6666666667%; } - - .col-lg-normal { - order: initial; } - - .col-lg-first { - order: -999; } - - .col-lg-last { - order: 999; } } -/* Card component CSS variable definitions */ -:root { - --card-back-color: #3cb4e6; - --card-fore-color: #03234b; - --card-border-color: #03234b; } - -.card { - display: flex; - flex-direction: column; - justify-content: space-between; - align-self: center; - position: relative; - width: 100%; - background: var(--card-back-color); - color: var(--card-fore-color); - border: 0.0714285714rem solid var(--card-border-color); - border-radius: var(--universal-border-radius); - margin: var(--universal-margin); - overflow: hidden; } - @media screen and (min-width: 320px) { - .card { - max-width: 320px; } } - .card > .sectione { - background: var(--card-back-color); - color: var(--card-fore-color); - box-sizing: border-box; - margin: 0; - border: 0; - border-radius: 0; - border-bottom: 0.0714285714rem solid var(--card-border-color); - padding: var(--universal-padding); - width: 100%; } - .card > .sectione.media { - height: 200px; - padding: 0; - -o-object-fit: cover; - object-fit: cover; } - .card > .sectione:last-child { - border-bottom: 0; } - -/* - Custom elements for card elements. -*/ -@media screen and (min-width: 240px) { - .card.small { - max-width: 240px; } } -@media screen and (min-width: 480px) { - .card.large { - max-width: 480px; } } -.card.fluid { - max-width: 100%; - width: auto; } - -.card.warning { - --card-back-color: #e5b8b7; - --card-fore-color: #3b234b; - --card-border-color: #8c0078; } - -.card.error { - --card-back-color: #464650; - --card-fore-color: #ffffff; - --card-border-color: #8c0078; } - -.card > .sectione.dark { - --card-back-color: #3b234b; - --card-fore-color: #ffffff; } - -.card > .sectione.double-padded { - padding: calc(1.5 * var(--universal-padding)); } - -/* - Definitions for forms and input elements. -*/ -/* Input_control module CSS variable definitions */ -:root { - --form-back-color: #ffe97f; - --form-fore-color: #03234b; - --form-border-color: #3cb4e6; - --input-back-color: #ffffff; - --input-fore-color: #03234b; - --input-border-color: #3cb4e6; - --input-focus-color: #0288d1; - --input-invalid-color: #d32f2f; - --button-back-color: #e2e2e2; - --button-hover-back-color: #dcdcdc; - --button-fore-color: #212121; - --button-border-color: transparent; - --button-hover-border-color: transparent; - --button-group-border-color: rgba(124, 124, 124, 0.54); } - -form { - background: var(--form-back-color); - color: var(--form-fore-color); - border: 0.0714285714rem solid var(--form-border-color); - border-radius: var(--universal-border-radius); - margin: var(--universal-margin); - padding: calc(2 * var(--universal-padding)) var(--universal-padding); } - -fieldset { - border: 0.0714285714rem solid var(--form-border-color); - border-radius: var(--universal-border-radius); - margin: calc(var(--universal-margin) / 4); - padding: var(--universal-padding); } - -legend { - box-sizing: border-box; - display: table; - max-width: 100%; - white-space: normal; - font-weight: 500; - padding: calc(var(--universal-padding) / 2); } - -label { - padding: calc(var(--universal-padding) / 2) var(--universal-padding); } - -.input-group { - display: inline-block; } - .input-group.fluid { - display: flex; - align-items: center; - justify-content: center; } - .input-group.fluid > input { - max-width: 100%; - flex-grow: 1; - flex-basis: 0px; } - @media screen and (max-width: 499px) { - .input-group.fluid { - align-items: stretch; - flex-direction: column; } } - .input-group.vertical { - display: flex; - align-items: stretch; - flex-direction: column; } - .input-group.vertical > input { - max-width: 100%; - flex-grow: 1; - flex-basis: 0px; } - -[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { - height: auto; } - -[type="search"] { - -webkit-appearance: textfield; - outline-offset: -2px; } - -[type="search"]::-webkit-search-cancel-button, -[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; } - -input:not([type]), [type="text"], [type="email"], [type="number"], [type="search"], -[type="password"], [type="url"], [type="tel"], [type="checkbox"], [type="radio"], textarea, select { - box-sizing: border-box; - background: var(--input-back-color); - color: var(--input-fore-color); - border: 0.0714285714rem solid var(--input-border-color); - border-radius: var(--universal-border-radius); - margin: calc(var(--universal-margin) / 2); - padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } - -input:not([type="button"]):not([type="submit"]):not([type="reset"]):hover, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus, textarea:hover, textarea:focus, select:hover, select:focus { - border-color: var(--input-focus-color); - box-shadow: none; } -input:not([type="button"]):not([type="submit"]):not([type="reset"]):invalid, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus:invalid, textarea:invalid, textarea:focus:invalid, select:invalid, select:focus:invalid { - border-color: var(--input-invalid-color); - box-shadow: none; } -input:not([type="button"]):not([type="submit"]):not([type="reset"])[readonly], textarea[readonly], select[readonly] { - background: var(--secondary-back-color); } - -select { - max-width: 100%; } - -option { - overflow: hidden; - text-overflow: ellipsis; } - -[type="checkbox"], [type="radio"] { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - position: relative; - height: calc(1rem + var(--universal-padding) / 2); - width: calc(1rem + var(--universal-padding) / 2); - vertical-align: text-bottom; - padding: 0; - flex-basis: calc(1rem + var(--universal-padding) / 2) !important; - flex-grow: 0 !important; } - [type="checkbox"]:checked:before, [type="radio"]:checked:before { - position: absolute; } - -[type="checkbox"]:checked:before { - content: '\2713'; - font-family: sans-serif; - font-size: calc(1rem + var(--universal-padding) / 2); - top: calc(0rem - var(--universal-padding)); - left: calc(var(--universal-padding) / 4); } - -[type="radio"] { - border-radius: 100%; } - [type="radio"]:checked:before { - border-radius: 100%; - content: ''; - top: calc(0.0714285714rem + var(--universal-padding) / 2); - left: calc(0.0714285714rem + var(--universal-padding) / 2); - background: var(--input-fore-color); - width: 0.5rem; - height: 0.5rem; } - -:placeholder-shown { - color: var(--input-fore-color); } - -::-ms-placeholder { - color: var(--input-fore-color); - opacity: 0.54; } - -button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { - border-style: none; - padding: 0; } - -button, html [type="button"], [type="reset"], [type="submit"] { - -webkit-appearance: button; } - -button { - overflow: visible; - text-transform: none; } - -button, [type="button"], [type="submit"], [type="reset"], -a.button, label.button, .button, -a[role="button"], label[role="button"], [role="button"] { - display: inline-block; - background: var(--button-back-color); - color: var(--button-fore-color); - border: 0.0714285714rem solid var(--button-border-color); - border-radius: var(--universal-border-radius); - padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); - margin: var(--universal-margin); - text-decoration: none; - cursor: pointer; - transition: background 0.3s; } - button:hover, button:focus, [type="button"]:hover, [type="button"]:focus, [type="submit"]:hover, [type="submit"]:focus, [type="reset"]:hover, [type="reset"]:focus, - a.button:hover, - a.button:focus, label.button:hover, label.button:focus, .button:hover, .button:focus, - a[role="button"]:hover, - a[role="button"]:focus, label[role="button"]:hover, label[role="button"]:focus, [role="button"]:hover, [role="button"]:focus { - background: var(--button-hover-back-color); - border-color: var(--button-hover-border-color); } - -input:disabled, input[disabled], textarea:disabled, textarea[disabled], select:disabled, select[disabled], button:disabled, button[disabled], .button:disabled, .button[disabled], [role="button"]:disabled, [role="button"][disabled] { - cursor: not-allowed; - opacity: 0.75; } - -.button-group { - display: flex; - border: 0.0714285714rem solid var(--button-group-border-color); - border-radius: var(--universal-border-radius); - margin: var(--universal-margin); } - .button-group > button, .button-group [type="button"], .button-group > [type="submit"], .button-group > [type="reset"], .button-group > .button, .button-group > [role="button"] { - margin: 0; - max-width: 100%; - flex: 1 1 auto; - text-align: center; - border: 0; - border-radius: 0; - box-shadow: none; } - .button-group > :not(:first-child) { - border-left: 0.0714285714rem solid var(--button-group-border-color); } - @media screen and (max-width: 499px) { - .button-group { - flex-direction: column; } - .button-group > :not(:first-child) { - border: 0; - border-top: 0.0714285714rem solid var(--button-group-border-color); } } - -/* - Custom elements for forms and input elements. -*/ -button.primary, [type="button"].primary, [type="submit"].primary, [type="reset"].primary, .button.primary, [role="button"].primary { - --button-back-color: #1976d2; - --button-fore-color: #f8f8f8; } - button.primary:hover, button.primary:focus, [type="button"].primary:hover, [type="button"].primary:focus, [type="submit"].primary:hover, [type="submit"].primary:focus, [type="reset"].primary:hover, [type="reset"].primary:focus, .button.primary:hover, .button.primary:focus, [role="button"].primary:hover, [role="button"].primary:focus { - --button-hover-back-color: #1565c0; } - -button.secondary, [type="button"].secondary, [type="submit"].secondary, [type="reset"].secondary, .button.secondary, [role="button"].secondary { - --button-back-color: #d32f2f; - --button-fore-color: #f8f8f8; } - button.secondary:hover, button.secondary:focus, [type="button"].secondary:hover, [type="button"].secondary:focus, [type="submit"].secondary:hover, [type="submit"].secondary:focus, [type="reset"].secondary:hover, [type="reset"].secondary:focus, .button.secondary:hover, .button.secondary:focus, [role="button"].secondary:hover, [role="button"].secondary:focus { - --button-hover-back-color: #c62828; } - -button.tertiary, [type="button"].tertiary, [type="submit"].tertiary, [type="reset"].tertiary, .button.tertiary, [role="button"].tertiary { - --button-back-color: #308732; - --button-fore-color: #f8f8f8; } - button.tertiary:hover, button.tertiary:focus, [type="button"].tertiary:hover, [type="button"].tertiary:focus, [type="submit"].tertiary:hover, [type="submit"].tertiary:focus, [type="reset"].tertiary:hover, [type="reset"].tertiary:focus, .button.tertiary:hover, .button.tertiary:focus, [role="button"].tertiary:hover, [role="button"].tertiary:focus { - --button-hover-back-color: #277529; } - -button.inverse, [type="button"].inverse, [type="submit"].inverse, [type="reset"].inverse, .button.inverse, [role="button"].inverse { - --button-back-color: #212121; - --button-fore-color: #f8f8f8; } - button.inverse:hover, button.inverse:focus, [type="button"].inverse:hover, [type="button"].inverse:focus, [type="submit"].inverse:hover, [type="submit"].inverse:focus, [type="reset"].inverse:hover, [type="reset"].inverse:focus, .button.inverse:hover, .button.inverse:focus, [role="button"].inverse:hover, [role="button"].inverse:focus { - --button-hover-back-color: #111; } - -button.small, [type="button"].small, [type="submit"].small, [type="reset"].small, .button.small, [role="button"].small { - padding: calc(0.5 * var(--universal-padding)) calc(0.75 * var(--universal-padding)); - margin: var(--universal-margin); } - -button.large, [type="button"].large, [type="submit"].large, [type="reset"].large, .button.large, [role="button"].large { - padding: calc(1.5 * var(--universal-padding)) calc(2 * var(--universal-padding)); - margin: var(--universal-margin); } - -/* - Definitions for navigation elements. -*/ -/* Navigation module CSS variable definitions */ -:root { - --header-back-color: #03234b; - --header-hover-back-color: #ffd200; - --header-fore-color: #ffffff; - --header-border-color: #3cb4e6; - --nav-back-color: #ffffff; - --nav-hover-back-color: #ffe97f; - --nav-fore-color: #e6007e; - --nav-border-color: #3cb4e6; - --nav-link-color: #3cb4e6; - --footer-fore-color: #ffffff; - --footer-back-color: #03234b; - --footer-border-color: #3cb4e6; - --footer-link-color: #3cb4e6; - --drawer-back-color: #ffffff; - --drawer-hover-back-color: #ffe97f; - --drawer-border-color: #3cb4e6; - --drawer-close-color: #e6007e; } - -header { - height: 2.75rem; - background: var(--header-back-color); - color: var(--header-fore-color); - border-bottom: 0.0714285714rem solid var(--header-border-color); - padding: calc(var(--universal-padding) / 4) 0; - white-space: nowrap; - overflow-x: auto; - overflow-y: hidden; } - header.row { - box-sizing: content-box; } - header .logo { - color: var(--header-fore-color); - font-size: 1.75rem; - padding: var(--universal-padding) calc(2 * var(--universal-padding)); - text-decoration: none; } - header button, header [type="button"], header .button, header [role="button"] { - box-sizing: border-box; - position: relative; - top: calc(0rem - var(--universal-padding) / 4); - height: calc(3.1875rem + var(--universal-padding) / 2); - background: var(--header-back-color); - line-height: calc(3.1875rem - var(--universal-padding) * 1.5); - text-align: center; - color: var(--header-fore-color); - border: 0; - border-radius: 0; - margin: 0; - text-transform: uppercase; } - header button:hover, header button:focus, header [type="button"]:hover, header [type="button"]:focus, header .button:hover, header .button:focus, header [role="button"]:hover, header [role="button"]:focus { - background: var(--header-hover-back-color); } - -nav { - background: var(--nav-back-color); - color: var(--nav-fore-color); - border: 0.0714285714rem solid var(--nav-border-color); - border-radius: var(--universal-border-radius); - margin: var(--universal-margin); } - nav * { - padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } - nav a, nav a:visited { - display: block; - color: var(--nav-link-color); - border-radius: var(--universal-border-radius); - transition: background 0.3s; } - nav a:hover, nav a:focus, nav a:visited:hover, nav a:visited:focus { - text-decoration: none; - background: var(--nav-hover-back-color); } - nav .sublink-1 { - position: relative; - margin-left: calc(2 * var(--universal-padding)); } - nav .sublink-1:before { - position: absolute; - left: calc(var(--universal-padding) - 1 * var(--universal-padding)); - top: -0.0714285714rem; - content: ''; - height: 100%; - border: 0.0714285714rem solid var(--nav-border-color); - border-left: 0; } - nav .sublink-2 { - position: relative; - margin-left: calc(4 * var(--universal-padding)); } - nav .sublink-2:before { - position: absolute; - left: calc(var(--universal-padding) - 3 * var(--universal-padding)); - top: -0.0714285714rem; - content: ''; - height: 100%; - border: 0.0714285714rem solid var(--nav-border-color); - border-left: 0; } - -footer { - background: var(--footer-back-color); - color: var(--footer-fore-color); - border-top: 0.0714285714rem solid var(--footer-border-color); - padding: calc(2 * var(--universal-padding)) var(--universal-padding); - font-size: 0.875rem; } - footer a, footer a:visited { - color: var(--footer-link-color); } - -header.sticky { - position: -webkit-sticky; - position: sticky; - z-index: 1101; - top: 0; } - -footer.sticky { - position: -webkit-sticky; - position: sticky; - z-index: 1101; - bottom: 0; } - -.drawer-toggle:before { - display: inline-block; - position: relative; - vertical-align: bottom; - content: '\00a0\2261\00a0'; - font-family: sans-serif; - font-size: 1.5em; } -@media screen and (min-width: 500px) { - .drawer-toggle:not(.persistent) { - display: none; } } - -[type="checkbox"].drawer { - height: 1px; - width: 1px; - margin: -1px; - overflow: hidden; - position: absolute; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); } - [type="checkbox"].drawer + * { - display: block; - box-sizing: border-box; - position: fixed; - top: 0; - width: 320px; - height: 100vh; - overflow-y: auto; - background: var(--drawer-back-color); - border: 0.0714285714rem solid var(--drawer-border-color); - border-radius: 0; - margin: 0; - z-index: 1110; - right: -320px; - transition: right 0.3s; } - [type="checkbox"].drawer + * .drawer-close { - position: absolute; - top: var(--universal-margin); - right: var(--universal-margin); - z-index: 1111; - width: 2rem; - height: 2rem; - border-radius: var(--universal-border-radius); - padding: var(--universal-padding); - margin: 0; - cursor: pointer; - transition: background 0.3s; } - [type="checkbox"].drawer + * .drawer-close:before { - display: block; - content: '\00D7'; - color: var(--drawer-close-color); - position: relative; - font-family: sans-serif; - font-size: 2rem; - line-height: 1; - text-align: center; } - [type="checkbox"].drawer + * .drawer-close:hover, [type="checkbox"].drawer + * .drawer-close:focus { - background: var(--drawer-hover-back-color); } - @media screen and (max-width: 320px) { - [type="checkbox"].drawer + * { - width: 100%; } } - [type="checkbox"].drawer:checked + * { - right: 0; } - @media screen and (min-width: 500px) { - [type="checkbox"].drawer:not(.persistent) + * { - position: static; - height: 100%; - z-index: 1100; } - [type="checkbox"].drawer:not(.persistent) + * .drawer-close { - display: none; } } - -/* - Definitions for the responsive table component. -*/ -/* Table module CSS variable definitions. */ -:root { - --table-border-color: #03234b; - --table-border-separator-color: #03234b; - --table-head-back-color: #03234b; - --table-head-fore-color: #ffffff; - --table-body-back-color: #ffffff; - --table-body-fore-color: #03234b; - --table-body-alt-back-color: #f4f4f4; } - -table { - border-collapse: separate; - border-spacing: 0; - margin: 0; - display: flex; - flex: 0 1 auto; - flex-flow: row wrap; - padding: var(--universal-padding); - padding-top: 0; } - table caption { - font-size: 1rem; - margin: calc(2 * var(--universal-margin)) 0; - max-width: 100%; - flex: 0 0 100%; } - table thead, table tbody { - display: flex; - flex-flow: row wrap; - border: 0.0714285714rem solid var(--table-border-color); } - table thead { - z-index: 999; - border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; - border-bottom: 0.0714285714rem solid var(--table-border-separator-color); } - table tbody { - border-top: 0; - margin-top: calc(0 - var(--universal-margin)); - border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } - table tr { - display: flex; - padding: 0; } - table th, table td { - padding: calc(0.5 * var(--universal-padding)); - font-size: 0.9rem; } - table th { - text-align: left; - background: var(--table-head-back-color); - color: var(--table-head-fore-color); } - table td { - background: var(--table-body-back-color); - color: var(--table-body-fore-color); - border-top: 0.0714285714rem solid var(--table-border-color); } - -table:not(.horizontal) { - overflow: auto; - max-height: 100%; } - table:not(.horizontal) thead, table:not(.horizontal) tbody { - max-width: 100%; - flex: 0 0 100%; } - table:not(.horizontal) tr { - flex-flow: row wrap; - flex: 0 0 100%; } - table:not(.horizontal) th, table:not(.horizontal) td { - flex: 1 0 0%; - overflow: hidden; - text-overflow: ellipsis; } - table:not(.horizontal) thead { - position: sticky; - top: 0; } - table:not(.horizontal) tbody tr:first-child td { - border-top: 0; } - -table.horizontal { - border: 0; } - table.horizontal thead, table.horizontal tbody { - border: 0; - flex: .2 0 0; - flex-flow: row nowrap; } - table.horizontal tbody { - overflow: auto; - justify-content: space-between; - flex: .8 0 0; - margin-left: 0; - padding-bottom: calc(var(--universal-padding) / 4); } - table.horizontal tr { - flex-direction: column; - flex: 1 0 auto; } - table.horizontal th, table.horizontal td { - width: auto; - border: 0; - border-bottom: 0.0714285714rem solid var(--table-border-color); } - table.horizontal th:not(:first-child), table.horizontal td:not(:first-child) { - border-top: 0; } - table.horizontal th { - text-align: right; - border-left: 0.0714285714rem solid var(--table-border-color); - border-right: 0.0714285714rem solid var(--table-border-separator-color); } - table.horizontal thead tr:first-child { - padding-left: 0; } - table.horizontal th:first-child, table.horizontal td:first-child { - border-top: 0.0714285714rem solid var(--table-border-color); } - table.horizontal tbody tr:last-child td { - border-right: 0.0714285714rem solid var(--table-border-color); } - table.horizontal tbody tr:last-child td:first-child { - border-top-right-radius: 0.25rem; } - table.horizontal tbody tr:last-child td:last-child { - border-bottom-right-radius: 0.25rem; } - table.horizontal thead tr:first-child th:first-child { - border-top-left-radius: 0.25rem; } - table.horizontal thead tr:first-child th:last-child { - border-bottom-left-radius: 0.25rem; } - -@media screen and (max-width: 499px) { - table, table.horizontal { - border-collapse: collapse; - border: 0; - width: 100%; - display: table; } - table thead, table th, table.horizontal thead, table.horizontal th { - border: 0; - height: 1px; - width: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); } - table tbody, table.horizontal tbody { - border: 0; - display: table-row-group; } - table tr, table.horizontal tr { - display: block; - border: 0.0714285714rem solid var(--table-border-color); - border-radius: var(--universal-border-radius); - background: #ffffff; - padding: var(--universal-padding); - margin: var(--universal-margin); - margin-bottom: calc(1 * var(--universal-margin)); } - table th, table td, table.horizontal th, table.horizontal td { - width: auto; } - table td, table.horizontal td { - display: block; - border: 0; - text-align: right; } - table td:before, table.horizontal td:before { - content: attr(data-label); - float: left; - font-weight: 600; } - table th:first-child, table td:first-child, table.horizontal th:first-child, table.horizontal td:first-child { - border-top: 0; } - table tbody tr:last-child td, table.horizontal tbody tr:last-child td { - border-right: 0; } } -table tr:nth-of-type(2n) > td { - background: var(--table-body-alt-back-color); } - -@media screen and (max-width: 500px) { - table tr:nth-of-type(2n) { - background: var(--table-body-alt-back-color); } } -:root { - --table-body-hover-back-color: #90caf9; } - -table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { - background: var(--table-body-hover-back-color); } - -@media screen and (max-width: 500px) { - table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { - background: var(--table-body-hover-back-color); } } -/* - Definitions for contextual background elements, toasts and tooltips. -*/ -/* Contextual module CSS variable definitions */ -:root { - --mark-back-color: #3cb4e6; - --mark-fore-color: #ffffff; } - -mark { - background: var(--mark-back-color); - color: var(--mark-fore-color); - font-size: 0.95em; - line-height: 1em; - border-radius: var(--universal-border-radius); - padding: calc(var(--universal-padding) / 4) var(--universal-padding); } - mark.inline-block { - display: inline-block; - font-size: 1em; - line-height: 1.4; - padding: calc(var(--universal-padding) / 2) var(--universal-padding); } - -:root { - --toast-back-color: #424242; - --toast-fore-color: #fafafa; } - -.toast { - position: fixed; - bottom: calc(var(--universal-margin) * 3); - left: 50%; - transform: translate(-50%, -50%); - z-index: 1111; - color: var(--toast-fore-color); - background: var(--toast-back-color); - border-radius: calc(var(--universal-border-radius) * 16); - padding: var(--universal-padding) calc(var(--universal-padding) * 3); } - -:root { - --tooltip-back-color: #212121; - --tooltip-fore-color: #fafafa; } - -.tooltip { - position: relative; - display: inline-block; } - .tooltip:before, .tooltip:after { - position: absolute; - opacity: 0; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); - transition: all 0.3s; - z-index: 1010; - left: 50%; } - .tooltip:not(.bottom):before, .tooltip:not(.bottom):after { - bottom: 75%; } - .tooltip.bottom:before, .tooltip.bottom:after { - top: 75%; } - .tooltip:hover:before, .tooltip:hover:after, .tooltip:focus:before, .tooltip:focus:after { - opacity: 1; - clip: auto; - -webkit-clip-path: inset(0%); - clip-path: inset(0%); } - .tooltip:before { - content: ''; - background: transparent; - border: var(--universal-margin) solid transparent; - left: calc(50% - var(--universal-margin)); } - .tooltip:not(.bottom):before { - border-top-color: #212121; } - .tooltip.bottom:before { - border-bottom-color: #212121; } - .tooltip:after { - content: attr(aria-label); - color: var(--tooltip-fore-color); - background: var(--tooltip-back-color); - border-radius: var(--universal-border-radius); - padding: var(--universal-padding); - white-space: nowrap; - transform: translateX(-50%); } - .tooltip:not(.bottom):after { - margin-bottom: calc(2 * var(--universal-margin)); } - .tooltip.bottom:after { - margin-top: calc(2 * var(--universal-margin)); } - -:root { - --modal-overlay-color: rgba(0, 0, 0, 0.45); - --modal-close-color: #e6007e; - --modal-close-hover-color: #ffe97f; } - -[type="checkbox"].modal { - height: 1px; - width: 1px; - margin: -1px; - overflow: hidden; - position: absolute; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); } - [type="checkbox"].modal + div { - position: fixed; - top: 0; - left: 0; - display: none; - width: 100vw; - height: 100vh; - background: var(--modal-overlay-color); } - [type="checkbox"].modal + div .card { - margin: 0 auto; - max-height: 50vh; - overflow: auto; } - [type="checkbox"].modal + div .card .modal-close { - position: absolute; - top: 0; - right: 0; - width: 1.75rem; - height: 1.75rem; - border-radius: var(--universal-border-radius); - padding: var(--universal-padding); - margin: 0; - cursor: pointer; - transition: background 0.3s; } - [type="checkbox"].modal + div .card .modal-close:before { - display: block; - content: '\00D7'; - color: var(--modal-close-color); - position: relative; - font-family: sans-serif; - font-size: 1.75rem; - line-height: 1; - text-align: center; } - [type="checkbox"].modal + div .card .modal-close:hover, [type="checkbox"].modal + div .card .modal-close:focus { - background: var(--modal-close-hover-color); } - [type="checkbox"].modal:checked + div { - display: flex; - flex: 0 1 auto; - z-index: 1200; } - [type="checkbox"].modal:checked + div .card .modal-close { - z-index: 1211; } - -:root { - --collapse-label-back-color: #03234b; - --collapse-label-fore-color: #ffffff; - --collapse-label-hover-back-color: #3cb4e6; - --collapse-selected-label-back-color: #3cb4e6; - --collapse-border-color: var(--collapse-label-back-color); - --collapse-selected-border-color: #ceecf8; - --collapse-content-back-color: #ffffff; - --collapse-selected-label-border-color: #3cb4e6; } - -.collapse { - width: calc(100% - 2 * var(--universal-margin)); - opacity: 1; - display: flex; - flex-direction: column; - margin: var(--universal-margin); - border-radius: var(--universal-border-radius); } - .collapse > [type="radio"], .collapse > [type="checkbox"] { - height: 1px; - width: 1px; - margin: -1px; - overflow: hidden; - position: absolute; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); } - .collapse > label { - flex-grow: 1; - display: inline-block; - height: 1.25rem; - cursor: pointer; - transition: background 0.2s; - color: var(--collapse-label-fore-color); - background: var(--collapse-label-back-color); - border: 0.0714285714rem solid var(--collapse-selected-border-color); - padding: calc(1.25 * var(--universal-padding)); } - .collapse > label:hover, .collapse > label:focus { - background: var(--collapse-label-hover-back-color); } - .collapse > label + div { - flex-basis: auto; - height: 1px; - width: 1px; - margin: -1px; - overflow: hidden; - position: absolute; - clip: rect(0 0 0 0); - -webkit-clip-path: inset(100%); - clip-path: inset(100%); - transition: max-height 0.3s; - max-height: 1px; } - .collapse > :checked + label { - background: var(--collapse-selected-label-back-color); - border-color: var(--collapse-selected-label-border-color); } - .collapse > :checked + label + div { - box-sizing: border-box; - position: relative; - width: 100%; - height: auto; - overflow: auto; - margin: 0; - background: var(--collapse-content-back-color); - border: 0.0714285714rem solid var(--collapse-selected-border-color); - border-top: 0; - padding: var(--universal-padding); - clip: auto; - -webkit-clip-path: inset(0%); - clip-path: inset(0%); - max-height: 100%; } - .collapse > label:not(:first-of-type) { - border-top: 0; } - .collapse > label:first-of-type { - border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; } - .collapse > label:last-of-type:not(:first-of-type) { - border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } - .collapse > label:last-of-type:first-of-type { - border-radius: var(--universal-border-radius); } - .collapse > :checked:last-of-type:not(:first-of-type) + label { - border-radius: 0; } - .collapse > :checked:last-of-type + label + div { - border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } - -/* - Custom elements for contextual background elements, toasts and tooltips. -*/ -mark.tertiary { - --mark-back-color: #3cb4e6; } - -mark.tag { - padding: calc(var(--universal-padding)/2) var(--universal-padding); - border-radius: 1em; } - -/* - Definitions for progress elements and spinners. -*/ -/* Progress module CSS variable definitions */ -:root { - --progress-back-color: #3cb4e6; - --progress-fore-color: #555; } - -progress { - display: block; - vertical-align: baseline; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - height: 0.75rem; - width: calc(100% - 2 * var(--universal-margin)); - margin: var(--universal-margin); - border: 0; - border-radius: calc(2 * var(--universal-border-radius)); - background: var(--progress-back-color); - color: var(--progress-fore-color); } - progress::-webkit-progress-value { - background: var(--progress-fore-color); - border-top-left-radius: calc(2 * var(--universal-border-radius)); - border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } - progress::-webkit-progress-bar { - background: var(--progress-back-color); } - progress::-moz-progress-bar { - background: var(--progress-fore-color); - border-top-left-radius: calc(2 * var(--universal-border-radius)); - border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } - progress[value="1000"]::-webkit-progress-value { - border-radius: calc(2 * var(--universal-border-radius)); } - progress[value="1000"]::-moz-progress-bar { - border-radius: calc(2 * var(--universal-border-radius)); } - progress.inline { - display: inline-block; - vertical-align: middle; - width: 60%; } - -:root { - --spinner-back-color: #ddd; - --spinner-fore-color: #555; } - -@keyframes spinner-donut-anim { - 0% { - transform: rotate(0deg); } - 100% { - transform: rotate(360deg); } } -.spinner { - display: inline-block; - margin: var(--universal-margin); - border: 0.25rem solid var(--spinner-back-color); - border-left: 0.25rem solid var(--spinner-fore-color); - border-radius: 50%; - width: 1.25rem; - height: 1.25rem; - animation: spinner-donut-anim 1.2s linear infinite; } - -/* - Custom elements for progress bars and spinners. -*/ -progress.primary { - --progress-fore-color: #1976d2; } - -progress.secondary { - --progress-fore-color: #d32f2f; } - -progress.tertiary { - --progress-fore-color: #308732; } - -.spinner.primary { - --spinner-fore-color: #1976d2; } - -.spinner.secondary { - --spinner-fore-color: #d32f2f; } - -.spinner.tertiary { - --spinner-fore-color: #308732; } - -/* - Definitions for icons - powered by Feather (https://feathericons.com/). -*/ -span[class^='icon-'] { - display: inline-block; - height: 1em; - width: 1em; - vertical-align: -0.125em; - background-size: contain; - margin: 0 calc(var(--universal-margin) / 4); } - span[class^='icon-'].secondary { - -webkit-filter: invert(25%); - filter: invert(25%); } - span[class^='icon-'].inverse { - -webkit-filter: invert(100%); - filter: invert(100%); } - -span.icon-alert { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12' y2='16'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-bookmark { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z'%3E%3C/path%3E%3C/svg%3E"); } -span.icon-calendar { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-credit { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1' y='4' width='22' height='16' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='1' y1='10' x2='23' y2='10'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-edit { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 14.66V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h5.34'%3E%3C/path%3E%3Cpolygon points='18 2 22 6 12 16 8 16 8 12 18 2'%3E%3C/polygon%3E%3C/svg%3E"); } -span.icon-link { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'%3E%3C/path%3E%3Cpolyline points='15 3 21 3 21 9'%3E%3C/polyline%3E%3Cline x1='10' y1='14' x2='21' y2='3'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-help { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3'%3E%3C/path%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='17' x2='12' y2='17'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-home { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'%3E%3C/path%3E%3Cpolyline points='9 22 9 12 15 12 15 22'%3E%3C/polyline%3E%3C/svg%3E"); } -span.icon-info { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='16' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='8' x2='12' y2='8'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-lock { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2' ry='2'%3E%3C/rect%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'%3E%3C/path%3E%3C/svg%3E"); } -span.icon-mail { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z'%3E%3C/path%3E%3Cpolyline points='22,6 12,13 2,6'%3E%3C/polyline%3E%3C/svg%3E"); } -span.icon-location { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z'%3E%3C/path%3E%3Ccircle cx='12' cy='10' r='3'%3E%3C/circle%3E%3C/svg%3E"); } -span.icon-phone { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z'%3E%3C/path%3E%3C/svg%3E"); } -span.icon-rss { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9'%3E%3C/path%3E%3Cpath d='M4 4a16 16 0 0 1 16 16'%3E%3C/path%3E%3Ccircle cx='5' cy='19' r='1'%3E%3C/circle%3E%3C/svg%3E"); } -span.icon-search { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-settings { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'%3E%3C/circle%3E%3Cpath d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z'%3E%3C/path%3E%3C/svg%3E"); } -span.icon-share { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='18' cy='5' r='3'%3E%3C/circle%3E%3Ccircle cx='6' cy='12' r='3'%3E%3C/circle%3E%3Ccircle cx='18' cy='19' r='3'%3E%3C/circle%3E%3Cline x1='8.59' y1='13.51' x2='15.42' y2='17.49'%3E%3C/line%3E%3Cline x1='15.41' y1='6.51' x2='8.59' y2='10.49'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-cart { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='21' r='1'%3E%3C/circle%3E%3Ccircle cx='20' cy='21' r='1'%3E%3C/circle%3E%3Cpath d='M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6'%3E%3C/path%3E%3C/svg%3E"); } -span.icon-upload { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'%3E%3C/path%3E%3Cpolyline points='17 8 12 3 7 8'%3E%3C/polyline%3E%3Cline x1='12' y1='3' x2='12' y2='15'%3E%3C/line%3E%3C/svg%3E"); } -span.icon-user { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%2303234b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'%3E%3C/path%3E%3Ccircle cx='12' cy='7' r='4'%3E%3C/circle%3E%3C/svg%3E"); } - -/* - Definitions for utilities and helper classes. -*/ -/* Utility module CSS variable definitions */ -:root { - --generic-border-color: rgba(0, 0, 0, 0.3); - --generic-box-shadow: 0 0.2857142857rem 0.2857142857rem 0 rgba(0, 0, 0, 0.125), 0 0.1428571429rem 0.1428571429rem -0.1428571429rem rgba(0, 0, 0, 0.125); } - -.hidden { - display: none !important; } - -.visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: -1px !important; - border: 0 !important; - padding: 0 !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(100%) !important; - clip-path: inset(100%) !important; - overflow: hidden !important; } - -.bordered { - border: 0.0714285714rem solid var(--generic-border-color) !important; } - -.rounded { - border-radius: var(--universal-border-radius) !important; } - -.circular { - border-radius: 50% !important; } - -.shadowed { - box-shadow: var(--generic-box-shadow) !important; } - -.responsive-margin { - margin: calc(var(--universal-margin) / 4) !important; } - @media screen and (min-width: 500px) { - .responsive-margin { - margin: calc(var(--universal-margin) / 2) !important; } } - @media screen and (min-width: 1280px) { - .responsive-margin { - margin: var(--universal-margin) !important; } } - -.responsive-padding { - padding: calc(var(--universal-padding) / 4) !important; } - @media screen and (min-width: 500px) { - .responsive-padding { - padding: calc(var(--universal-padding) / 2) !important; } } - @media screen and (min-width: 1280px) { - .responsive-padding { - padding: var(--universal-padding) !important; } } - -@media screen and (max-width: 499px) { - .hidden-sm { - display: none !important; } } -@media screen and (min-width: 500px) and (max-width: 1279px) { - .hidden-md { - display: none !important; } } -@media screen and (min-width: 1280px) { - .hidden-lg { - display: none !important; } } -@media screen and (max-width: 499px) { - .visually-hidden-sm { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: -1px !important; - border: 0 !important; - padding: 0 !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(100%) !important; - clip-path: inset(100%) !important; - overflow: hidden !important; } } -@media screen and (min-width: 500px) and (max-width: 1279px) { - .visually-hidden-md { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: -1px !important; - border: 0 !important; - padding: 0 !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(100%) !important; - clip-path: inset(100%) !important; - overflow: hidden !important; } } -@media screen and (min-width: 1280px) { - .visually-hidden-lg { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: -1px !important; - border: 0 !important; - padding: 0 !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(100%) !important; - clip-path: inset(100%) !important; - overflow: hidden !important; } } - -/*# sourceMappingURL=mini-custom.css.map */ - -img[alt="ST logo"] { display: block; margin: auto; width: 75%; max-width: 250px; min-width: 71px; } -img[alt="Cube logo"] { float: right; width: 30%; max-width: 10rem; min-width: 8rem; padding-right: 1rem;} - -.figure { - display: block; - margin-left: auto; - margin-right: auto; - text-align: center; -} diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/st_logo_2020.png b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/_htmresc/st_logo_2020.png deleted file mode 100644 index d6cebb5ac70e0594cbe37a6b60036a80ef3bed37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7520 zcmcI|WmKC@*KTl!K!Z~t6qn*&DDF_CK%q#B6QmH_DHL}I6b%;K-J$eBN|2xh0+bea zmtyV5bG|?CpZBcu=iF<}z4q*xz1LhL*PcBwx;m;Pgmi=e0DweYO-UaBz)*UWZ}4#+ zCC-V!SC16}H#HLv0Dy?%--0o{5_}H;Jf%=ql7H=+dziOk_)KzUSaiQ9L<^g!49k}} z?4y$V zrsn3Ul^TY`00G_J_8;F7Sr5c3Y)f-yOYl{fS0avfKJg7R%r!y-ohcBkr6XBZBkE)( z_t+tVV2}G1_CN!)yWes*wa-AGwk31N_T1`)4COlfz+o(9S90e?6jHV4)!>`j+oRqp z)gb?rtSdw<#&c?q!OKB+Ncn!kr5JR2EYan8HAPXBw*Oh-F(6GmaC!`$p7fl!_Cdu> z5@PUMR_K5&jgevDepWqepZVdMHR$q>ga=7k0ltW$HHVn>HRa!#(+BW_jN$5rx^MtR zzWT7tNWQeFzEp+86jOYI=I)*GZYEiXlf-Mw%tJ^ptL%2)%#PmUjxC4wx@%KxQ)8kO?|7E1 zd@5gd9_$*6nx?fj*iF_EJT*PYLFP}d8*Fw>cu3@&nm%V_C}V7HMmg|Nl#1J1^#)uz zZag|X>{6j-myvL}3(H8o3resNBq_jcuJuyT!QuXnNN&zG^tG? z>y*dy1#XfwyCE#UiLT(~LYAVwp)epErJLsHBA|l0xo)kxLAPob+7tFlr{7x8(#v|O zknK}QC6|~=cTJ0;x9MWMKua;LdTKIHX>35a@7{5y0MQ|zqsP64mM~`gJ&&R{pSUBA zf3Y>k>d|xdzBFztjtO~{y%@LUdwSgzEj=69hH3-NNWx7<|49%2%lvTEeE3_|$~iDd zlktnxf|NB>Bui)yY;%TXgWA;rhODxR!-4GzxKd473I)3;j zS4-Vun<^vqZ4)HbwVzq%5%)S!>Q(Y&PkF ze1ab_oy?_$PZT-mKJ3K^;6MrB*Wc$lkYJ_460AFYEq{AjlDxm;5GRwOsm>doJy3Z;a$FSu-q`X)Hw&o~?_`Dnpx4dOj6#)bGOdZbj4hD`l|&#v~K+WrGO zpLCVQg=*h=4H1sK)D*Pxtb#p`c+g-eK65k!CEZjLIrfm}5<4@KVqZ#8(S$vs{?Xv) zN(}CKeeLR%I)W!p(l-`utKmBbJk-On{)ciqUN5%?TS8uwKU(8}Mxhsb&qHL~DDcB@qi} z4z%efV#K69a#lShPt5}*7ME@^xunFR{k;|qp z`_Hgdj_Qle?%Ydlr3f^SdRkUncIj7qTiu85tA$v`#419Nlof8tjqUjO z!Rwyq$Krfh`(@MiE+)yie&jU^crprYV&?zN!2b33S2qtW+zB$nahDhVZiQ12bmcwYBcT8KS>v`jsuI@X zy^k^7>TM5Ndp@}pSl6vmkk*u`@C`z(gq||K2>y=Y#w1i`Nk2zAP7{_^ACq;bQmT<4 z;b~K3=?mhZX#~jQnZjdU={NFp^HRr~;^PXQ*UIHzkq}Xsn!56*ZCOOEt|^ zawUwGqs;zCEGKTz&(a(@h#0sCE+@`3Y<&}9!(;Pw&`C+d#D?`##&!@*ERaH0fksrh zfk2svh3!d~h{SC6BNKN2j6(lzC>S^_*eh{@gR zP$rV4$nqV1y|zYpd;nQr-`Vlp(5sQXx9AibC?xc7pUV)v2cWfHu3{KLbfP;;;`I&)mWqLcXt6s+5fps9R?K>hGR$5;=( zo#;zzQ5!w+(99p1_gh^?F#$tpMd+4%G|K`XG_#@A>30WD2L9!0a>wRASg`M?^z#)| zifb$d^KUD&3qLsr-@}r_7p${gdmRqhy819bj?yI-v({I?0o3_8d>CZmCzqH4{{QtD z|6dvgm<^~668G`6wLw4C4y-o9E9ZG3RiH^&;rrKSBT@bMR+!TlYo*9P;?Z>xORMV3ndQp9EyNn!!~j&x&$gDVke|t#!{QoegHm+sT7cSjwSu z)jZlx1pHrrx0&YCZWJ4xC&U%r_IwfJOxnYqYMcZn&_hgnKuls z>(Y$qjIhcweo^A_VVq_#UR&urF%UbI^><5L5zbV9owMQviM*_{@i|dke!!v8a_yG! zl%#ay{(6U_N3-)yeif3tx6>aQSf1r zO~OuNW<8a~bi6Xby0@tKw0@f1R!@+3S2nf#F&j~l0mrNCtjoZdPYob?g!Vx4F-uA2 z4uS>8eR?dA9i>C|cm-m5lO0m@$f(DB6Z<9Pe07xR`l4$ks3eZ@v5}1?^YNQy-tB(` zgUNZrGVf#b~`}jew;MQG1O~VDk_i*<)p9DfFfd;vLy4QZT zMYh|DxJg3-!{szUN*uo&`&DUkzq4qG2`Lj;Ar46DYUymcviS{Unhzmx z=LwZ-Lr{t1z?9Oip%!z{j+Z%_@u?C78I`V4fC`icG1c|2;`EoLK$ z)9|wrAV&V1Vgts~tQCw0X?X{74W"NJQ zW3BP!5c~4zzHJScwQK9L_%m%L`*q{1aW_3rObki~B~=Dwp`;@w`>xZ6;L_6oR^ecEcmup`yb}lgsmv zQByrxc)Qqm(Hwmq%fLjqcrJ5QR?z_*vb~Iy~RXUY8u-D8AqTzetwNNA8~N z$j&1>#IrkSslUqXW|l}q_TlTVKAjRI@~7(GLf4M>GM!3u_)y6ORe6BQUmrQ16%OdZKo(?AYXK$u@=)TPUi1EZaLBu zuEB(5GX2vcoHS%zMUW!DZ)&xRo@mhouk|hMgHIG>cO-Ah(0AMNlq@?cPpy==-!#qR zBov7l3G?P*KM(vU;Apo-(-Bw;sdQJkh~r)W$KRQKd!#(A8M34^MhD10Ra={AqSvjy z3>PkgA}f^@Rg1$dX=jaEB_V%_vn(W<111_s!g>CYrcwJTJ63Eeg6{_C`aMQIgKctR zHMjkr+y6gK!v6=6;CGl#?PqmiX`A@dmmvZ}-X$*q8}G(xq|voo`=$YZuQAa8f9ApK z1VQiEUQC=OO{|Nc8ZrXH208X|XCzIRO?+Nb55Jt@va9hqBpv)uY6ma-csvSlJoJOC zK;w~s?#r)K@gm*;((JsWHU-KvFTF)q>AzwPq)I+}OrSpxh!-CM1VEMfw1fpfVL7p{ z)I$rNp5kPYDsvXL>8nV{#0fa*lm`Z;0Z=c^1qveY2uk&7nhMRl`0EsvUuvwdF&o)PCVN3wmFBPegWzooF6y~b} zY>X2;LO~&rbvx59?(4^aR+s1C6hI4r&x9Q9jL9);KZEw_x%TWZXaMzK6|2XG9$IU% zkEq}t^YOaa4s`%7F31X-#SfMgNp+4R=g2G|O^W)6^2fEsmkTTaVhKCip+3qWuN8?y zaSD_k6%-@Ifhm`z02=ZWA-pi5`A=7ztHWpP2K5rCW{>!wIUOYrH``#bz>qVSH76=8 zyJ!sNBxt;dMTn}yzUTCq1!w;N7pzb?WJrQ50W+`meL{k8i0VhFsPUz(07k`l` zg1Ifl1fc-^p^MQCpK~Jk&L!*mWfNA!&MSu`sPmti>K-;I5Dk00nB3vOl4!JwjEx^X zWQsIp2Ea_>`9f@%zGl4i3FAO9=e$2^b_>_I*dqiLJ=@TejStM?^yX$9dW`#ha)PEF zPr0zUJX!j-juYK*olG_9axQniXhF|E}oSTG_S)FZ3sN4T@q zy{l;!{UGc};YVaT97tx3s7P$WsW2^*I+Hy;vqndG!9S?tZtDIRif1=bBsqtW-n7$O zWy}Z%jKSkgLX#1p>|#4l-!$c+kA`++Ixv(Rm`;Ilb3q3tD|QjaPQ8)BJ=8R*15?nL zJR{yuqOG&!JrSZ${#NY#b!k)yDajQ$A}fUQhe7ueN6h2Pj3wY5eo|7$PaJD zM69(ee1qlSyLn)Ln6)o53Lj)elqG}gb^c}qd(q&$8B5N%nSvEjUIoEXO^obv=A7QGZzNzjO*H=*b2!86Wnqdy~8ePkq@1D1)Q^O)JG;fUCV z`rgD}dJ{7BUyBbgoTL91w^q-CfBpDr?0R38`L%p9&Q#%r*@=9p-Ioqy+WscLq?jq5 zfyYNkxr7w)-(!c85mt!FjNJ4UE6P8p8sc#Kb4L1N3!yaCo9@t3n8s}K)1!w8x77xU zo-NY3SR*Pgt#~7F;y^J&Y%z^+C9wu;hN|TC7dqSHOB&kE)Q)6Ad(l&+tA@$@w0bhJ z6xc6EJ6nm{=|V7Vo&qcXc4i)D?X0Uk$p7~iI#ci?#fxvM z78`u%m5S@^_F;_foidufzP z&ueh-zU1yM&8~0lmOfkio-gBex`)?hCJcI8Jv*R0c|WUqSq z?RU?Rmm=3t_2C%%UW9c*D%T{T{EjryCKnsz9-*Bs0}M*xS&-odhCK5eS_Eqi&c6J4o|f&;uUT=p7Fedw#EUl4%Jv{w zq-cCF^otBvw~~$yj6O>>;VqU)3Ml&Atm$B(Ht8=+&x2VS5aWD&t*+04{@k^Gn~yHY zWYC%@ld;g_qz=k*;Iv&xs5M85cEZCU&n2Baf>R6*bN>V|!)eF&l#C93eAMLD=ZF7= zOISFfB5P;F!ngWD3jfMJE_53F&dFc{h2TwSbT*(h6!c}_5_UFeB_*DiyCrtQ7Byr@ z-aCWVt?J}YP7-lfelbrCgZ5mdv(^W&Yf^OvpI}#NbS1Lc`r4&t#3kM!utm&#a;?GR z-1FusfX7&?a9h`%8wf-ub7UXp44xm4w04)S$}}_hPqn-#IabO^bo6$K07>?%G5Xs( zA$*lz_K>lAJ_o<;fsP-*-%~O(716KRqVq+X@=5J~Z~bba(yWL`;EN`@Mr2it&Lkgb z&I|R5!`ZSk%)xFX*FYDaAh=5qWSY@rx1Du9J$$=lh#!~NcFJM&aOv)eqg_@`i^zJCR9a%_{k_i%msw5q z*3!~#Xx3r|VaAwiG}~9M#c`=$Uk6~xe)47ymW+;0DD_lV67L#ouJBa7mF{)X^?eIvPdOMu4ksr`jUP$~{x@?ev2 zdX#ite2RMim01PEg`;qfwg^;v8nx9F!CtNCvz)V{PVgCs*;_@_Rk*oLx@f7hJ7^^1 zu66b)mb!ZMXLZ%8dj-+JCMoWS-Wji-Q-~U7Pt~UiXMej8JcNjk<6?Wk9eLBIhu&Vo^0;AH> z;Q5^a!NZhP(vDfBv&?jdnQavv#8N0E{ZEgs>|1)qYo^t5 zIV$g~`C2%g$*(z4)8hJlK2mF-MJW#3%Cs6`uAvsgRtTo8n!Et)1pZx@_9I18 zw7ER9v~DyrC*R$do9aEw5r@B)YzHOLB^-c9Eu9D!sFmI8^VljVKE89{zY_8PTSF+J b^}%0^qYmp2WD(pA|JtZ4>nPPKybJpu3@X?! diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.c b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.c deleted file mode 100644 index 952ff16c9..000000000 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.c +++ /dev/null @@ -1,886 +0,0 @@ -/** - ****************************************************************************** - * @file tcpp0203.c - * @author MCD Application Team - * @brief This file provides the TCPP02/03 Type-C port protection driver. - ****************************************************************************** - * @attention - * - * Copyright (c) 2021 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "tcpp0203.h" - -#if defined(_TRACE) -#include "usbpd_core.h" -#include "usbpd_trace.h" -#include "string.h" -#include "stdio.h" -#endif /* _TRACE */ - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup Components - * @{ - */ - -/** @addtogroup TCPP0203 - * @brief This file provides a set of functions needed to drive the - * TCPP02/03 Type-C port protection. - * @{ - */ - -/** @defgroup TCPP0203_Private_Constants Private Constants - * @{ - */ - -/* Compilation option in order to enable/disable a concistency check performed - after each I2C access into TCPP0203 registers : goal is to check that written value in Reg0 - is properly reflected into reg1 register content. - To enable register consistency check, please uncomment below definition. - To disable it, comment below line */ -/* #define TCPP0203_REGISTER_CONSISTENCY_CHECK */ - -/** @defgroup TCPP0203_Private_Types Private Types - * @{ - */ -/* TCPP02/03 Type-C port protection driver structure initialization */ -TCPP0203_Drv_t TCPP0203_Driver = -{ - TCPP0203_Init, - TCPP0203_DeInit, - TCPP0203_Reset, - TCPP0203_SetVConnSwitch, - TCPP0203_SetGateDriverProvider, - TCPP0203_SetGateDriverConsumer, - TCPP0203_SetPowerMode, - TCPP0203_SetVBusDischarge, - TCPP0203_SetVConnDischarge, - TCPP0203_GetVConnSwitchAck, - TCPP0203_GetGateDriverProviderAck, - TCPP0203_GetGateDriverConsumerAck, - TCPP0203_GetPowerModeAck, - TCPP0203_GetVBusDischargeAck, - TCPP0203_GetVConnDischargeAck, - TCPP0203_GetOCPVConnFlag, - TCPP0203_GetOCPVBusFlag, - TCPP0203_GetOVPVBusFlag, - TCPP0203_GetOVPCCFlag, - TCPP0203_GetOTPFlag, - TCPP0203_GetVBusOkFlag, - TCPP0203_ReadTCPPType, - TCPP0203_ReadVCONNPower, - TCPP0203_WriteCtrlRegister, - TCPP0203_ReadAckRegister, - TCPP0203_ReadFlagRegister, -}; - -/** - * @} - */ - -/** @defgroup TCPP0203_Private_Variables Private Variables - * @{ - */ -static uint8_t TCPP0203_DeviceType = TCPP0203_DEVICE_TYPE_03; - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) -static uint8_t Reg0_Expected_Value = 0x00; -static uint8_t Reg1_LastRead_Value = 0x00; -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - -/** - * @} - */ - -/* Private function prototypes -----------------------------------------------*/ - -/** @defgroup TCPP0203_Private_Function_Prototypes TCPP0203 Private Function Prototypes - * @{ - */ -static int32_t TCPP0203_ReadRegWrap(const void *handle, uint8_t Reg, uint8_t *Data, uint8_t Length); -static int32_t TCPP0203_WriteRegWrap(const void *handle, uint8_t Reg, uint8_t *Data, uint8_t Length); - -static int32_t TCPP0203_ModifyReg0(TCPP0203_Object_t *pObj, uint8_t Value, uint8_t Mask); - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) -static int32_t TCPP0203_CheckReg0Reg1(TCPP0203_Object_t *pObj, uint8_t Reg0ExpectedValue); -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - -/** - * @} - */ - -/** @defgroup TCPP0203_Exported_Functions TCPP0203 Exported Functions - * @{ - */ - -/** - * @brief Register Bus Io to component - * @param Component object pointer - * @retval Status of execution - */ -int32_t TCPP0203_RegisterBusIO(TCPP0203_Object_t *pObj, TCPP0203_IO_t *pIO) -{ - int32_t ret; - - if (pObj == NULL) - { - ret = TCPP0203_ERROR; - } - else - { - pObj->IO.Init = pIO->Init; - pObj->IO.DeInit = pIO->DeInit; - pObj->IO.Address = pIO->Address; - pObj->IO.WriteReg = pIO->WriteReg; - pObj->IO.ReadReg = pIO->ReadReg; - pObj->IO.GetTick = pIO->GetTick; - - pObj->Ctx.ReadReg = TCPP0203_ReadRegWrap; - pObj->Ctx.WriteReg = TCPP0203_WriteRegWrap; - pObj->Ctx.handle = pObj; - - if (pObj->IO.Init != NULL) - { - ret = pObj->IO.Init(); - } - else - { - ret = TCPP0203_ERROR; - } - } - - return ret; -} - -/** - * @brief Initializes the TCPP0203 interface - * @param pObj Pointer to component object - * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) - */ -int32_t TCPP0203_Init(TCPP0203_Object_t *pObj) -{ - int32_t ret = 0; - uint8_t tmp; - - if (pObj->IsInitialized == 0U) - { - /* Read TCPP Device type */ - ret += tcpp0203_read_reg(&pObj->Ctx, TCPP0203_READ_REG2, &tmp, 1); - - if (ret == TCPP0203_OK) - { - TCPP0203_DeviceType = (tmp & TCPP0203_DEVICE_TYPE_MSK); - } - else - { - TCPP0203_DeviceType = TCPP0203_DEVICE_TYPE_02; - } - pObj->IsInitialized = 1U; - } - - if (ret != TCPP0203_OK) - { - ret = TCPP0203_ERROR; - } - - return ret; -} - -/** - * @brief Deinitializes the TCPP0203 interface - * @param pObj Pointer to component object - * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) - */ -int32_t TCPP0203_DeInit(TCPP0203_Object_t *pObj) -{ - if (pObj->IsInitialized == 1U) - { - /* De-Initialize IO BUS layer */ - pObj->IO.DeInit(); - - pObj->IsInitialized = 0U; - } - - return TCPP0203_OK; -} - -/** - * @brief Resets TCPP0203 register (Reg0) - * @param pObj Pointer to component object - * @retval Component status (TCPP0203_OK / TCPP0203_ERROR) - */ -int32_t TCPP0203_Reset(TCPP0203_Object_t *pObj) -{ - int32_t ret = TCPP0203_OK; - uint8_t tmp = TCPP0203_REG0_RST_VALUE; - - /* Write reset values in Reg0 register */ - if (tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, &tmp, 1) != TCPP0203_OK) - { - ret = TCPP0203_ERROR; - } - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) - Reg0_Expected_Value = TCPP0203_REG0_RST_VALUE; - Reg1_LastRead_Value = TCPP0203_REG0_RST_VALUE; -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - - return ret; -} - -/** - * @brief Configure TCPP0203 VConn Switch - * @param pObj Pointer to component object - * @param VConnSwitch VConn Switch requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_VCONN_SWITCH_OPEN VConn switch open - * @arg TCPP0203_VCONN_SWITCH_CC1 VConn closed on CC1 - * @arg TCPP0203_VCONN_SWITCH_CC2 VConn closed on CC2 - * @retval Component status - */ -int32_t TCPP0203_SetVConnSwitch(TCPP0203_Object_t *pObj, uint8_t VConnSwitch) -{ - int32_t ret = TCPP0203_OK; - - if ((VConnSwitch != TCPP0203_VCONN_SWITCH_OPEN) - && (VConnSwitch != TCPP0203_VCONN_SWITCH_CC1) - && (VConnSwitch != TCPP0203_VCONN_SWITCH_CC2)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update VConn switch setting in Writing register Reg0 */ - ret += TCPP0203_ModifyReg0(pObj, VConnSwitch, TCPP0203_VCONN_SWITCH_MSK); - } - - return ret; -} - -/** - * @brief Configure TCPP0203 Gate Driver for Provider path - * @param pObj Pointer to component object - * @param GateDriverProvider GDP switch load requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_GD_PROVIDER_SWITCH_OPEN GDP Switch Load Open - * @arg TCPP0203_GD_PROVIDER_SWITCH_CLOSED GDP Switch Load closed - * @retval Component status - */ -int32_t TCPP0203_SetGateDriverProvider(TCPP0203_Object_t *pObj, uint8_t GateDriverProvider) -{ - int32_t ret = TCPP0203_OK; - - if ((GateDriverProvider != TCPP0203_GD_PROVIDER_SWITCH_OPEN) - && (GateDriverProvider != TCPP0203_GD_PROVIDER_SWITCH_CLOSED)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update GDP Switch Load setting in Writing register Reg0 */ - if (GateDriverProvider == TCPP0203_GD_PROVIDER_SWITCH_CLOSED) - { - /* If Gate Driver Provider is to be closed, Gate Driver Consumer should be open */ - ret += TCPP0203_ModifyReg0(pObj, (GateDriverProvider | TCPP0203_GD_CONSUMER_SWITCH_OPEN), - (TCPP0203_GD_PROVIDER_SWITCH_MSK | TCPP0203_GD_CONSUMER_SWITCH_MSK)); - } - else - { - ret += TCPP0203_ModifyReg0(pObj, GateDriverProvider, TCPP0203_GD_PROVIDER_SWITCH_MSK); - } - } - - return ret; -} - -/** - * @brief Configure TCPP0203 Gate Driver for Consumer path - * @param pObj Pointer to component object - * @param GateDriverConsumer GDC switch load requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_GD_CONSUMER_SWITCH_OPEN GDC Switch Load Open - * @arg TCPP0203_GD_CONSUMER_SWITCH_CLOSED GDC Switch Load closed - * @retval Component status - */ -int32_t TCPP0203_SetGateDriverConsumer(TCPP0203_Object_t *pObj, uint8_t GateDriverConsumer) -{ - int32_t ret = TCPP0203_OK; - - /* Check if TCPP type is TCPP03. Otherwise, return error */ - if (TCPP0203_DeviceType != TCPP0203_DEVICE_TYPE_03) - { - return (TCPP0203_ERROR); - } - - if ((GateDriverConsumer != TCPP0203_GD_CONSUMER_SWITCH_OPEN) - && (GateDriverConsumer != TCPP0203_GD_CONSUMER_SWITCH_CLOSED)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update GDC Switch Load setting in Writing register Reg0 */ - if (GateDriverConsumer == TCPP0203_GD_CONSUMER_SWITCH_CLOSED) - { - /* If Gate Driver Consumer is to be closed, Gate Driver Provider should be open */ - ret += TCPP0203_ModifyReg0(pObj, (GateDriverConsumer | TCPP0203_GD_PROVIDER_SWITCH_OPEN), - (TCPP0203_GD_PROVIDER_SWITCH_MSK | TCPP0203_GD_CONSUMER_SWITCH_MSK)); - } - else - { - ret += TCPP0203_ModifyReg0(pObj, GateDriverConsumer, TCPP0203_GD_CONSUMER_SWITCH_MSK); - } - } - - return ret; -} - -/** - * @brief Configure TCPP0203 Power Mode - * @param pObj Pointer to component object - * @param PowerMode Power mode requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_POWER_MODE_HIBERNATE Hibernate - * @arg TCPP0203_POWER_MODE_LOWPOWER Low Power - * @arg TCPP0203_POWER_MODE_NORMAL Normal - * @retval Component status - */ -int32_t TCPP0203_SetPowerMode(TCPP0203_Object_t *pObj, uint8_t PowerMode) -{ - int32_t ret = TCPP0203_OK; - - if ((PowerMode != TCPP0203_POWER_MODE_HIBERNATE) - && (PowerMode != TCPP0203_POWER_MODE_LOWPOWER) - && (PowerMode != TCPP0203_POWER_MODE_NORMAL)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update Power Mode setting in Writing register Reg0 */ - ret += TCPP0203_ModifyReg0(pObj, PowerMode, TCPP0203_POWER_MODE_MSK); - } - - return ret; -} - -/** - * @brief Configure TCPP0203 Gate Driver for Provider path - * @param pObj Pointer to component object - * @param VBusDischarge VBUS Discharge requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_VBUS_DISCHARGE_OFF VBUS Discharge Off - * @arg TCPP0203_VBUS_DISCHARGE_ON VBUS Discharge On - * @retval Component status - */ -int32_t TCPP0203_SetVBusDischarge(TCPP0203_Object_t *pObj, uint8_t VBusDischarge) -{ - int32_t ret = TCPP0203_OK; - - if ((VBusDischarge != TCPP0203_VBUS_DISCHARGE_OFF) - && (VBusDischarge != TCPP0203_VBUS_DISCHARGE_ON)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update VBUS Discharge setting in Writing register Reg0 */ - ret += TCPP0203_ModifyReg0(pObj, VBusDischarge, TCPP0203_VBUS_DISCHARGE_MSK); - } - - return ret; -} - -/** - * @brief Configure TCPP0203 Gate Driver for Provider path - * @param pObj Pointer to component object - * @param VConnDischarge GDP switch load requested setting - * This parameter can be one of the following values: - * @arg TCPP0203_VCONN_DISCHARGE_OFF VConn Discharge Off - * @arg TCPP0203_VCONN_DISCHARGE_ON VConn Discharge On - * @retval Component status - */ -int32_t TCPP0203_SetVConnDischarge(TCPP0203_Object_t *pObj, uint8_t VConnDischarge) -{ - int32_t ret = TCPP0203_OK; - - if ((VConnDischarge != TCPP0203_VCONN_DISCHARGE_OFF) - && (VConnDischarge != TCPP0203_VCONN_DISCHARGE_ON)) - { - ret = TCPP0203_ERROR; - } - else - { - /* Update VConn Discharge setting in Writing register Reg0 */ - ret += TCPP0203_ModifyReg0(pObj, VConnDischarge, TCPP0203_VCONN_DISCHARGE_MSK); - } - - return ret; -} - -/** - * @brief Get VConn switch Ack value - * @param pObj Pointer to component object - * @param pVConnSwitchAck Pointer on VConn switch Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_VCONN_SWITCH_OPEN VConn switch open Ack - * @arg TCPP0203_VCONN_SWITCH_CC1 VConn closed on CC1 Ack - * @arg TCPP0203_VCONN_SWITCH_CC2 VConn closed on CC2 Ack - * @retval Component status - */ -int32_t TCPP0203_GetVConnSwitchAck(TCPP0203_Object_t *pObj, uint8_t *pVConnSwitchAck) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pVConnSwitchAck = (tmp & TCPP0203_VCONN_SWITCH_ACK_MSK); - - return ret; -} - -/** - * @brief Get Gate Driver Provider Ack value - * @param pObj Pointer to component object - * @param pGateDriverProviderAck Pointer on Gate Driver Provider Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_GD_PROVIDER_SWITCH_ACK_OPEN Gate Driver Provider Open Ack - * @arg TCPP0203_GD_PROVIDER_SWITCH_ACK_CLOSED Gate Driver Provider Closed Ack - * @retval Component status - */ -int32_t TCPP0203_GetGateDriverProviderAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverProviderAck) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pGateDriverProviderAck = (tmp & TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK); - - return ret; -} - -/** - * @brief Get Gate Driver Consumer Ack value - * @param pObj Pointer to component object - * @param pGateDriverConsumerAck Pointer on Gate Driver Consumer Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_GD_CONSUMER_SWITCH_ACK_OPEN Gate Driver Consumer Open Ack - * @arg TCPP0203_GD_CONSUMER_SWITCH_ACK_CLOSED Gate Driver Consumer Closed Ack - * @retval Component status - */ -int32_t TCPP0203_GetGateDriverConsumerAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverConsumerAck) -{ - int32_t ret; - uint8_t tmp; - - /* Check if TCPP type is TCPP03. Otherwise, return error */ - if (TCPP0203_DeviceType != TCPP0203_DEVICE_TYPE_03) - { - return (TCPP0203_ERROR); - } - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pGateDriverConsumerAck = (tmp & TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK); - - return ret; -} - -/** - * @brief Get Power Mode Ack value - * @param pObj Pointer to component object - * @param pPowerModeAck Pointer on Power Mode Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_POWER_MODE_ACK_HIBERNATE Power Mode Hibernate Ack - * @arg TCPP0203_POWER_MODE_ACK_LOWPOWER Power Mode Low Power Ack - * @arg TCPP0203_POWER_MODE_ACK_NORMAL Power Mode Normal Ack - * @retval Component status - */ -int32_t TCPP0203_GetPowerModeAck(TCPP0203_Object_t *pObj, uint8_t *pPowerModeAck) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pPowerModeAck = (tmp & TCPP0203_POWER_MODE_ACK_MSK); - - return ret; -} - -/** - * @brief Get VBUS Discharge Ack value - * @param pObj Pointer to component object - * @param pVBusDischargeAck Pointer on VBUS Discharge Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_VBUS_DISCHARGE_ACK_OFF VBUS Discharge Off Ack - * @arg TCPP0203_VBUS_DISCHARGE_ACK_ON VBUS Discharge On Ack - * @retval Component status - */ -int32_t TCPP0203_GetVBusDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVBusDischargeAck) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pVBusDischargeAck = (tmp & TCPP0203_VBUS_DISCHARGE_ACK_MSK); - - return ret; -} - -/** - * @brief Get VConn Discharge Ack value - * @param pObj Pointer to component object - * @param pVConnDischargeAck Pointer on VConn Discharge Ack value - * This output parameter can be one of the following values: - * @arg TCPP0203_VCONN_DISCHARGE_ACK_OFF VConn Discharge Off Ack - * @arg TCPP0203_VCONN_DISCHARGE_ACK_ON VConn Discharge On Ack - * @retval Component status - */ -int32_t TCPP0203_GetVConnDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVConnDischargeAck) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - *pVConnDischargeAck = (tmp & TCPP0203_VCONN_DISCHARGE_ACK_MSK); - - return ret; -} - -/** - * @brief Get OCP VConn Flag value - * @param pObj Pointer to component object - * @param pOCPVConnFlag Pointer on OCP VConn Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_OCP_VCONN_RESET OCP VConn flag not set - * @arg TCPP0203_FLAG_OCP_VCONN_SET OCP VConn flag set - * @retval Component status - */ -int32_t TCPP0203_GetOCPVConnFlag(TCPP0203_Object_t *pObj, uint8_t *pOCPVConnFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pOCPVConnFlag = (tmp & TCPP0203_FLAG_OCP_VCONN_MSK); - - return ret; -} - -/** - * @brief Get OCP VBUS Flag value - * @param pObj Pointer to component object - * @param pGetOCPVBusFlag Pointer on OCP VBUS Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_OCP_VBUS_RESET OCP VBUS flag not set - * @arg TCPP0203_FLAG_OCP_VBUS_SET OCP VBUS flag set - * @retval Component status - */ -int32_t TCPP0203_GetOCPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pGetOCPVBusFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pGetOCPVBusFlag = (tmp & TCPP0203_FLAG_OCP_VBUS_MSK); - - return ret; -} - -/** - * @brief Get OVP VBUS Flag value - * @param pObj Pointer to component object - * @param pOVPVBusFlag Pointer on OVP VBUS Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_OVP_VBUS_RESET OVP VBUS flag not set - * @arg TCPP0203_FLAG_OVP_VBUS_SET OVP VBUS flag set - * @retval Component status - */ -int32_t TCPP0203_GetOVPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPVBusFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pOVPVBusFlag = (tmp & TCPP0203_FLAG_OVP_VBUS_MSK); - - return ret; -} - -/** - * @brief Get OVP CC Flag value - * @param pObj Pointer to component object - * @param pOVPCCFlag Pointer on OVP CC Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_OVP_CC_RESET OVP CC flag not set - * @arg TCPP0203_FLAG_OVP_CC_SET OVP CC flag set - * @retval Component status - */ -int32_t TCPP0203_GetOVPCCFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPCCFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pOVPCCFlag = (tmp & TCPP0203_FLAG_OVP_CC_MSK); - - return ret; -} - -/** - * @brief Get Over Temperature Flag value - * @param pObj Pointer to component object - * @param pOTPFlag Pointer on Over Temperature Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_OTP_RESET Over Temperature flag not set - * @arg TCPP0203_FLAG_OTP_SET Over Temperature flag set - * @retval Component status - */ -int32_t TCPP0203_GetOTPFlag(TCPP0203_Object_t *pObj, uint8_t *pOTPFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pOTPFlag = (tmp & TCPP0203_FLAG_OTP_MSK); - - return ret; -} - -/** - * @brief Get VBUS OK Flag value - * @param pObj Pointer to component object - * @param pVBusOkFlag Pointer on VBUS OK Flag value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_VBUS_OK_RESET VBUS OK flag not set - * @arg TCPP0203_FLAG_VBUS_OK_SET VBUS OK flag set - * @retval Component status - */ -int32_t TCPP0203_GetVBusOkFlag(TCPP0203_Object_t *pObj, uint8_t *pVBusOkFlag) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pVBusOkFlag = (tmp & TCPP0203_FLAG_VBUS_OK_MSK); - - return ret; -} - -/** - * @brief Get TCPP0203 Device Type value - * @param pObj Pointer to component object - * @param pTCPPType Pointer on TCPP0203 Device Type value - * This output parameter can be one of the following values: - * @arg TCPP0203_DEVICE_TYPE_02 TCPP02 Type - * @arg TCPP0203_DEVICE_TYPE_03 TCPP03 Type - * @retval Component status - */ -int32_t TCPP0203_ReadTCPPType(TCPP0203_Object_t *pObj, uint8_t *pTCPPType) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pTCPPType = (tmp & TCPP0203_DEVICE_TYPE_MSK); - - return ret; -} - -/** - * @brief Get VConn Power value - * @param pObj Pointer to component object - * @param pVCONNPower Pointer on VConn Power value - * This output parameter can be one of the following values: - * @arg TCPP0203_FLAG_VCONN_PWR_1W OCP VConn flag not set - * @arg TCPP0203_FLAG_VCONN_PWR_0_1W OCP VConn flag set - * @retval Component status - */ -int32_t TCPP0203_ReadVCONNPower(TCPP0203_Object_t *pObj, uint8_t *pVCONNPower) -{ - int32_t ret; - uint8_t tmp; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, &tmp, 1); - *pVCONNPower = (tmp & TCPP0203_FLAG_VCONN_PWR_MSK); - - return ret; -} - -/** - * @brief Set complete Ctrl register value (Reg 0) - * @param pObj Pointer to component object - * @param pCtrlRegister Pointer on Ctrl register value - * @retval Component status - */ -int32_t TCPP0203_WriteCtrlRegister(TCPP0203_Object_t *pObj, uint8_t *pCtrlRegister) -{ - int32_t ret; - - /* Update value in writing register (reg0) */ - ret = tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, pCtrlRegister, 1); - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) - Reg0_Expected_Value = *pCtrlRegister; -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - - return ret; -} - -/** - * @brief Get complete Ack register value - * @param pObj Pointer to component object - * @param pAckRegister Pointer on Ack register value - * @retval Component status - */ -int32_t TCPP0203_ReadAckRegister(TCPP0203_Object_t *pObj, uint8_t *pAckRegister) -{ - int32_t ret; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, pAckRegister, 1); - - return ret; -} - -/** - * @brief Get complete Flag register value - * @param pObj Pointer to component object - * @param pFlagRegister Pointer on Flag register value - * @retval Component status - */ -int32_t TCPP0203_ReadFlagRegister(TCPP0203_Object_t *pObj, uint8_t *pFlagRegister) -{ - int32_t ret; - - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_FLAG_REG, pFlagRegister, 1); - - return ret; -} - -/******************** Static functions ****************************************/ -/** - * @brief Wrap TCPP0203 read function to Bus IO function - * @param handle Component object handle - * @param Reg Target register address to read - * @param pData Buffer where Target register value should be stored - * @param Length buffer size to be read - * @retval error status - */ -static int32_t TCPP0203_ReadRegWrap(const void *handle, uint8_t Reg, uint8_t *pData, uint8_t Length) -{ - const TCPP0203_Object_t *pObj = (const TCPP0203_Object_t *)handle; - - return pObj->IO.ReadReg(pObj->IO.Address, Reg, pData, Length); -} - -/** - * @brief Wrap TCPP0203 write function to Bus IO function - * @param handle Component object handle - * @param Reg Target register address to write - * @param pData Target register value to be written - * @param Length Buffer size to be written - * @retval error status - */ -static int32_t TCPP0203_WriteRegWrap(const void *handle, uint8_t Reg, uint8_t *pData, uint8_t Length) -{ - const TCPP0203_Object_t *pObj = (const TCPP0203_Object_t *)handle; - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) - Reg0_Expected_Value = *pData; -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - - return pObj->IO.WriteReg(pObj->IO.Address, Reg, pData, Length); -} - -/** - * @brief TCPP0203 register update function to Bus IO function - * @param handle Component object handle - * @param Reg Target register address to write - * @param pData Target register value to be written - * @param Length Buffer size to be written - * @retval error status - */ -static int32_t TCPP0203_ModifyReg0(TCPP0203_Object_t *pObj, uint8_t Value, uint8_t Mask) -{ - int32_t ret; - uint8_t tmp; - - /* Read current content of ACK register (reflects content of bits set to 1 in Writing register Reg0) */ - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &tmp, 1); - - /* Update only the area dedicated to Mask */ - tmp &= ~(Mask); - tmp |= (Value & Mask); - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) - Reg0_Expected_Value = tmp; -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - - /* Update value in writing register (reg0) */ - ret += tcpp0203_write_reg(&pObj->Ctx, TCPP0203_PROG_CTRL, &tmp, 1); - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) - ret += TCPP0203_CheckReg0Reg1(pObj, Reg0_Expected_Value); -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - - return ret; -} - -#if defined(TCPP0203_REGISTER_CONSISTENCY_CHECK) -/** - * @brief TCPP0203 register control function between Reg0 and Reg1 value - * @param handle Component object handle - * @param Reg0ExpectedValue Value expected in Reg0 (built after all calls to write functions) - * @retval error status - */ -static int32_t TCPP0203_CheckReg0Reg1(TCPP0203_Object_t *pObj, uint8_t Reg0ExpectedValue) -{ - int32_t ret; - - /* Read current content of ACK register (expected to reflect content of bits set to 1 in Writing register Reg0) */ - ret = tcpp0203_read_reg(&pObj->Ctx, TCPP0203_ACK_REG, &Reg1_LastRead_Value, 1); - -#ifdef _TRACE - char str[12]; - sprintf(str, "Exp0_0x%02x", Reg0ExpectedValue); - USBPD_TRACE_Add(USBPD_TRACE_DEBUG, 0U, 0U, (uint8_t *)str, sizeof(str) - 1U); - sprintf(str, "Reg1_0x%02x", Reg1_LastRead_Value); - USBPD_TRACE_Add(USBPD_TRACE_DEBUG, 0U, 0U, (uint8_t *)str, sizeof(str) - 1U); -#endif /* _TRACE */ - - /* Control if Reg1 value is same as Reg0 expected one */ - if (Reg1_LastRead_Value != Reg0ExpectedValue) - { - while (1); - } - - return ret; -} -#endif /* TCPP0203_REGISTER_CONSISTENCY_CHECK */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.h b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.h deleted file mode 100644 index 271b534fc..000000000 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203.h +++ /dev/null @@ -1,353 +0,0 @@ -/** - ****************************************************************************** - * @file tcpp0203.h - * @author MCD Application Team - * @brief This file contains all the functions prototypes for the - * tcpp0203.c driver. - ****************************************************************************** - * @attention - * - * Copyright (c) 2021 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef TCPP0203_H -#define TCPP0203_H - -/* Includes ------------------------------------------------------------------*/ -#include "tcpp0203_reg.h" -#include - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup Component - * @{ - */ - -/** @addtogroup TCPP0203 - * @{ - */ - -/* Exported types ------------------------------------------------------------*/ - -/** @defgroup TCPP0203_Exported_Types TCPP0203 Exported Types - * @{ - */ -typedef int32_t (*TCPP0203_Init_Func)(void); -typedef int32_t (*TCPP0203_DeInit_Func)(void); -typedef int32_t (*TCPP0203_GetTick_Func)(void); -typedef int32_t (*TCPP0203_WriteReg_Func)(uint16_t, uint16_t, uint8_t *, uint16_t); -typedef int32_t (*TCPP0203_ReadReg_Func)(uint16_t, uint16_t, uint8_t *, uint16_t); - -typedef struct -{ - TCPP0203_Init_Func Init; - TCPP0203_DeInit_Func DeInit; - uint16_t Address; - TCPP0203_WriteReg_Func WriteReg; - TCPP0203_ReadReg_Func ReadReg; - TCPP0203_GetTick_Func GetTick; -} TCPP0203_IO_t; - - -typedef struct -{ - TCPP0203_IO_t IO; - TCPP0203_ctx_t Ctx; - uint8_t IsInitialized; -} TCPP0203_Object_t; - -typedef struct -{ - int32_t (*Init)(TCPP0203_Object_t *); - int32_t (*DeInit)(TCPP0203_Object_t *); - int32_t (*Reset)(TCPP0203_Object_t *); - int32_t (*SetVConnSwitch)(TCPP0203_Object_t *, uint8_t); - int32_t (*SetGateDriverProvider)(TCPP0203_Object_t *, uint8_t); - int32_t (*SetGateDriverConsumer)(TCPP0203_Object_t *, uint8_t); - int32_t (*SetPowerMode)(TCPP0203_Object_t *, uint8_t); - int32_t (*SetVBusDischarge)(TCPP0203_Object_t *, uint8_t); - int32_t (*SetVConnDischarge)(TCPP0203_Object_t *, uint8_t); - int32_t (*GetVConnSwitchAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetGateDriverProviderAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetGateDriverConsumerAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetPowerModeAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetVBusDischargeAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetVConnDischargeAck)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetOCPVConnFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetOCPVBusFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetOVPVBusFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetOVPCCFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetOTPFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*GetVBusOkFlag)(TCPP0203_Object_t *, uint8_t *); - int32_t (*ReadTCPPType)(TCPP0203_Object_t *, uint8_t *); - int32_t (*ReadVCONNPower)(TCPP0203_Object_t *, uint8_t *); - int32_t (*WriteCtrlRegister)(TCPP0203_Object_t *, uint8_t *); - int32_t (*ReadAckRegister)(TCPP0203_Object_t *, uint8_t *); - int32_t (*ReadFlagRegister)(TCPP0203_Object_t *, uint8_t *); -} TCPP0203_Drv_t; - -/** - * @} - */ - -/** @defgroup TCPP0203_Exported_Constants TCPP0203 Exported Constants - * @{ - */ -/** - * @brief TCPP0203 Driver Response codes - */ -#define TCPP0203_OK (0) -#define TCPP0203_ERROR (-1) - -/** - * @brief TCPP0203 possible I2C Addresses - */ -#define TCPP0203_I2C_ADDRESS_X68 (0x68U) -#define TCPP0203_I2C_ADDRESS_X6A (0x6AU) - -/** - * @brief TCPP0203 Reg0 Reset Value - */ -#define TCPP0203_REG0_RST_VALUE TCPP0203_GD_CONSUMER_SWITCH_CLOSED - -/** - * @brief TCPP0203 VCONN Switch - */ -#define TCPP0203_VCONN_SWITCH_POS (0U) -#define TCPP0203_VCONN_SWITCH_MSK (0x03U << TCPP0203_VCONN_SWITCH_POS) -#define TCPP0203_VCONN_SWITCH_OPEN (0x00U) -#define TCPP0203_VCONN_SWITCH_CC1 (0x01U << TCPP0203_VCONN_SWITCH_POS) -#define TCPP0203_VCONN_SWITCH_CC2 (0x02U << TCPP0203_VCONN_SWITCH_POS) - -/** - * @brief TCPP0203 Gate Driver Provider values - */ -#define TCPP0203_GD_PROVIDER_SWITCH_POS (2U) -#define TCPP0203_GD_PROVIDER_SWITCH_MSK (0x01U << TCPP0203_GD_PROVIDER_SWITCH_POS) -#define TCPP0203_GD_PROVIDER_SWITCH_OPEN (0x00U) -#define TCPP0203_GD_PROVIDER_SWITCH_CLOSED (TCPP0203_GD_PROVIDER_SWITCH_MSK) - -/** - * @brief TCPP0203 Gate Driver Consumer values - */ -#define TCPP0203_GD_CONSUMER_SWITCH_POS (3U) -#define TCPP0203_GD_CONSUMER_SWITCH_MSK (0x01U << TCPP0203_GD_CONSUMER_SWITCH_POS) -#define TCPP0203_GD_CONSUMER_SWITCH_CLOSED (0x00U) -#define TCPP0203_GD_CONSUMER_SWITCH_OPEN (TCPP0203_GD_CONSUMER_SWITCH_MSK) - -/** - * @brief TCPP0203 Power Mode values - */ -#define TCPP0203_POWER_MODE_POS (4U) -#define TCPP0203_POWER_MODE_MSK (0x03U << TCPP0203_POWER_MODE_POS) -#define TCPP0203_POWER_MODE_HIBERNATE (0x00U) -#define TCPP0203_POWER_MODE_LOWPOWER (0x02U << TCPP0203_POWER_MODE_POS) -#define TCPP0203_POWER_MODE_NORMAL (0x01U << TCPP0203_POWER_MODE_POS) - -/** - * @brief TCPP0203 VBUS Discharge management - */ -#define TCPP0203_VBUS_DISCHARGE_POS (6U) -#define TCPP0203_VBUS_DISCHARGE_MSK (0x01U << TCPP0203_VBUS_DISCHARGE_POS) -#define TCPP0203_VBUS_DISCHARGE_OFF (0x00U) -#define TCPP0203_VBUS_DISCHARGE_ON (TCPP0203_VBUS_DISCHARGE_MSK) - -/** - * @brief TCPP0203 VConn Discharge management - */ -#define TCPP0203_VCONN_DISCHARGE_POS (7U) -#define TCPP0203_VCONN_DISCHARGE_MSK (0x01U << TCPP0203_VCONN_DISCHARGE_POS) -#define TCPP0203_VCONN_DISCHARGE_OFF (0x00U) -#define TCPP0203_VCONN_DISCHARGE_ON (TCPP0203_VCONN_DISCHARGE_MSK) - -/** - * @brief TCPP0203 VCONN Switch Acknowledge - */ -#define TCPP0203_VCONN_SWITCH_ACK_POS (0U) -#define TCPP0203_VCONN_SWITCH_ACK_MSK (0x03U << TCPP0203_VCONN_SWITCH_ACK_POS) -#define TCPP0203_VCONN_SWITCH_ACK_OPEN (0x00U) -#define TCPP0203_VCONN_SWITCH_ACK_CC1 (0x02U << TCPP0203_VCONN_SWITCH_ACK_POS) -#define TCPP0203_VCONN_SWITCH_ACK_CC2 (0x01U << TCPP0203_VCONN_SWITCH_ACK_POS) - -/** - * @brief TCPP0203 Gate Driver Provider Acknowledge - */ -#define TCPP0203_GD_PROVIDER_SWITCH_ACK_POS (2U) -#define TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK (0x01U << TCPP0203_GD_PROVIDER_SWITCH_ACK_POS) -#define TCPP0203_GD_PROVIDER_SWITCH_ACK_OPEN (0x00U) -#define TCPP0203_GD_PROVIDER_SWITCH_ACK_CLOSED (TCPP0203_GD_PROVIDER_SWITCH_ACK_MSK) - -/** - * @brief TCPP0203 Gate Driver Consumer Acknowledge - */ -#define TCPP0203_GD_CONSUMER_SWITCH_ACK_POS (3U) -#define TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK (0x01U << TCPP0203_GD_CONSUMER_SWITCH_ACK_POS) -#define TCPP0203_GD_CONSUMER_SWITCH_ACK_CLOSED (0x00U) -#define TCPP0203_GD_CONSUMER_SWITCH_ACK_OPEN (TCPP0203_GD_CONSUMER_SWITCH_ACK_MSK) - -/** - * @brief TCPP0203 Power Mode Acknowledge - */ -#define TCPP0203_POWER_MODE_ACK_POS (4U) -#define TCPP0203_POWER_MODE_ACK_MSK (0x03U << TCPP0203_POWER_MODE_ACK_POS) -#define TCPP0203_POWER_MODE_ACK_HIBERNATE (0x00U) -#define TCPP0203_POWER_MODE_ACK_LOWPOWER (0x01U << TCPP0203_POWER_MODE_ACK_POS) -#define TCPP0203_POWER_MODE_ACK_NORMAL (0x02U << TCPP0203_POWER_MODE_ACK_POS) - -/** - * @brief TCPP0203 VBUS Discharge Acknowledge - */ -#define TCPP0203_VBUS_DISCHARGE_ACK_POS (6U) -#define TCPP0203_VBUS_DISCHARGE_ACK_MSK (0x01U << TCPP0203_VBUS_DISCHARGE_ACK_POS) -#define TCPP0203_VBUS_DISCHARGE_ACK_OFF (0x00U) -#define TCPP0203_VBUS_DISCHARGE_ACK_ON (TCPP0203_VBUS_DISCHARGE_ACK_MSK) - -/** - * @brief TCPP0203 VConn Discharge Acknowledge - */ -#define TCPP0203_VCONN_DISCHARGE_ACK_POS (7U) -#define TCPP0203_VCONN_DISCHARGE_ACK_MSK (0x01U << TCPP0203_VCONN_DISCHARGE_ACK_POS) -#define TCPP0203_VCONN_DISCHARGE_ACK_OFF (0x00U) -#define TCPP0203_VCONN_DISCHARGE_ACK_ON (TCPP0203_VCONN_DISCHARGE_ACK_MSK) - -/** - * @brief TCPP0203 OCP Vconn Flag management - */ -#define TCPP0203_FLAG_OCP_VCONN_POS (0U) -#define TCPP0203_FLAG_OCP_VCONN_MSK (0x01U << TCPP0203_FLAG_OCP_VCONN_POS) -#define TCPP0203_FLAG_OCP_VCONN_SET (TCPP0203_FLAG_OCP_VCONN_MSK) -#define TCPP0203_FLAG_OCP_VCONN_RESET (0x00U) - -/** - * @brief TCPP0203 OCP VBUS Flag management - */ -#define TCPP0203_FLAG_OCP_VBUS_POS (1U) -#define TCPP0203_FLAG_OCP_VBUS_MSK (0x01U << TCPP0203_FLAG_OCP_VBUS_POS) -#define TCPP0203_FLAG_OCP_VBUS_SET (TCPP0203_FLAG_OCP_VBUS_MSK) -#define TCPP0203_FLAG_OCP_VBUS_RESET (0x00U) - -/** - * @brief TCPP0203 OVP VBUS Flag management - */ -#define TCPP0203_FLAG_OVP_VBUS_POS (2U) -#define TCPP0203_FLAG_OVP_VBUS_MSK (0x01U << TCPP0203_FLAG_OVP_VBUS_POS) -#define TCPP0203_FLAG_OVP_VBUS_SET (TCPP0203_FLAG_OVP_VBUS_MSK) -#define TCPP0203_FLAG_OVP_VBUS_RESET (0x00U) - -/** - * @brief TCPP0203 OVP CC Flag management - */ -#define TCPP0203_FLAG_OVP_CC_POS (3U) -#define TCPP0203_FLAG_OVP_CC_MSK (0x01U << TCPP0203_FLAG_OVP_CC_POS) -#define TCPP0203_FLAG_OVP_CC_SET (TCPP0203_FLAG_OVP_CC_MSK) -#define TCPP0203_FLAG_OVP_CC_RESET (0x00U) - -/** - * @brief TCPP0203 OTP Flag management - */ -#define TCPP0203_FLAG_OTP_POS (4U) -#define TCPP0203_FLAG_OTP_MSK (0x01U << TCPP0203_FLAG_OTP_POS) -#define TCPP0203_FLAG_OTP_SET (TCPP0203_FLAG_OTP_MSK) -#define TCPP0203_FLAG_OTP_RESET (0x00U) - -/** - * @brief TCPP0203 VBUS OK Flag management - */ -#define TCPP0203_FLAG_VBUS_OK_POS (5U) -#define TCPP0203_FLAG_VBUS_OK_MSK (0x01U << TCPP0203_FLAG_VBUS_OK_POS) -#define TCPP0203_FLAG_VBUS_OK_SET (TCPP0203_FLAG_VBUS_OK_MSK) -#define TCPP0203_FLAG_VBUS_OK_RESET (0x00U) - -/** - * @brief TCPP0203 VConn Power - */ -#define TCPP0203_FLAG_VCONN_PWR_POS (6U) -#define TCPP0203_FLAG_VCONN_PWR_MSK (0x01U << TCPP0203_FLAG_VCONN_PWR_POS) -#define TCPP0203_FLAG_VCONN_PWR_1W (TCPP0203_FLAG_VCONN_PWR_MSK) -#define TCPP0203_FLAG_VCONN_PWR_0_1W (0x00U) - -/** - * @brief TCPP0203 Device Type - */ -#define TCPP0203_DEVICE_TYPE_POS (7U) -#define TCPP0203_DEVICE_TYPE_MSK (0x01U << TCPP0203_DEVICE_TYPE_POS) -#define TCPP0203_DEVICE_TYPE_02 (TCPP0203_DEVICE_TYPE_MSK) -#define TCPP0203_DEVICE_TYPE_03 (0x00U) - -/** - * @} - */ - -/** @defgroup TCPP0203_Exported_Macros TCPP0203 Exported Macros - * @{ - */ -/** - * @} - */ - -/** @defgroup TCPP0203_Exported_Functions TCPP0203 Exported Functions - * @{ - */ - -/*------------------------------------------------------------------------------ - TCPP02/03 Type-C port protection functions -------------------------------------------------------------------------------*/ -/* High Layer codec functions */ -int32_t TCPP0203_RegisterBusIO(TCPP0203_Object_t *pObj, TCPP0203_IO_t *pIO); -int32_t TCPP0203_Init(TCPP0203_Object_t *pObj); -int32_t TCPP0203_DeInit(TCPP0203_Object_t *pObj); -int32_t TCPP0203_Reset(TCPP0203_Object_t *pObj); -int32_t TCPP0203_SetVConnSwitch(TCPP0203_Object_t *pObj, uint8_t VConnSwitch); -int32_t TCPP0203_SetGateDriverProvider(TCPP0203_Object_t *pObj, uint8_t GateDriverProvider); -int32_t TCPP0203_SetGateDriverConsumer(TCPP0203_Object_t *pObj, uint8_t GateDriverConsumer); -int32_t TCPP0203_SetPowerMode(TCPP0203_Object_t *pObj, uint8_t PowerMode); -int32_t TCPP0203_SetVBusDischarge(TCPP0203_Object_t *pObj, uint8_t VBusDischarge); -int32_t TCPP0203_SetVConnDischarge(TCPP0203_Object_t *pObj, uint8_t VConnDischarge); -int32_t TCPP0203_GetVConnSwitchAck(TCPP0203_Object_t *pObj, uint8_t *pVConnSwitchAck); -int32_t TCPP0203_GetGateDriverProviderAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverProviderAck); -int32_t TCPP0203_GetGateDriverConsumerAck(TCPP0203_Object_t *pObj, uint8_t *pGateDriverConsumerAck); -int32_t TCPP0203_GetPowerModeAck(TCPP0203_Object_t *pObj, uint8_t *pPowerModeAck); -int32_t TCPP0203_GetVBusDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVBusDischargeAck); -int32_t TCPP0203_GetVConnDischargeAck(TCPP0203_Object_t *pObj, uint8_t *pVConnDischargeAck); -int32_t TCPP0203_GetOCPVConnFlag(TCPP0203_Object_t *pObj, uint8_t *pOCPVConnFlag); -int32_t TCPP0203_GetOCPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pGetOCPVBusFlag); -int32_t TCPP0203_GetOVPVBusFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPVBusFlag); -int32_t TCPP0203_GetOVPCCFlag(TCPP0203_Object_t *pObj, uint8_t *pOVPCCFlag); -int32_t TCPP0203_GetOTPFlag(TCPP0203_Object_t *pObj, uint8_t *pOTPFlag); -int32_t TCPP0203_GetVBusOkFlag(TCPP0203_Object_t *pObj, uint8_t *pVBusOkFlag); -int32_t TCPP0203_ReadTCPPType(TCPP0203_Object_t *pObj, uint8_t *pTCPPType); -int32_t TCPP0203_ReadVCONNPower(TCPP0203_Object_t *pObj, uint8_t *pVCONNPower); -int32_t TCPP0203_WriteCtrlRegister(TCPP0203_Object_t *pObj, uint8_t *pCtrlRegister); -int32_t TCPP0203_ReadAckRegister(TCPP0203_Object_t *pObj, uint8_t *pAckRegister); -int32_t TCPP0203_ReadFlagRegister(TCPP0203_Object_t *pObj, uint8_t *pFlagRegister); - -/** - * @} - */ - -/* TCPP02/03 Type-C port protection driver structure */ -extern TCPP0203_Drv_t TCPP0203_Driver; - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#endif /* TCPP0203_H */ diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.c b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.c deleted file mode 100644 index 8025fa85e..000000000 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.c +++ /dev/null @@ -1,73 +0,0 @@ -/** - ****************************************************************************** - * @file tcpp0203_reg.c - * @author MCD Application Team - * @brief This file provides unitary register function to control the TCPP02-03 - * Type-C port protection driver. - ****************************************************************************** - * @attention - * - * Copyright (c) 2021 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "tcpp0203_reg.h" - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup Components - * @{ - */ - -/** @addtogroup TCPP0203 - * @brief This file provides a set of functions needed to drive the - * TCPP02/03 Type-C port protection codec. - * @{ - */ - -/************** Generic Function *******************/ -/******************************************************************************* - * Function Name : tcpp0203_read_reg - * Description : Generic Reading function. It must be fulfilled with either - * I2C or SPI reading functions - * Input : Register Address, length of buffer - * Output : data Read - *******************************************************************************/ -int32_t tcpp0203_read_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length) -{ - return ctx->ReadReg(ctx->handle, reg, data, length); -} - -/******************************************************************************* - * Function Name : tcpp0203_write_reg - * Description : Generic Writing function. It must be fulfilled with either - * I2C or SPI writing function - * Input : Register Address, data to be written, length of buffer - * Output : None - *******************************************************************************/ -int32_t tcpp0203_write_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length) -{ - return ctx->WriteReg(ctx->handle, reg, data, length); -} - -/******************************************************************************/ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.h b/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.h deleted file mode 100644 index 92420e1fe..000000000 --- a/hw/bsp/stm32n6/boards/stm32n657nucleo/tcpp0203/tcpp0203_reg.h +++ /dev/null @@ -1,98 +0,0 @@ -/** - ****************************************************************************** - * @file tcpp0203_reg.h - * @author MCD Application Team - * @brief Header of tcpp0203_reg.c - * - ****************************************************************************** - * @attention - * - * Copyright (c) 2021 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef TCPP0203_REG_H -#define TCPP0203_REG_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup Component - * @{ - */ - -/** @addtogroup TCPP0203 - * @{ - */ - - -/** @defgroup TCPP0203_Exported_Constants TCPP0203 Exported Constants - * @{ - */ -/******************************************************************************/ -/****************************** REGISTER MAPPING ******************************/ -/******************************************************************************/ -#define TCPP0203_WRITE_REG 0x00U -#define TCPP0203_PROG_CTRL TCPP0203_WRITE_REG -#define TCPP0203_READ_REG1 0x01U -#define TCPP0203_ACK_REG TCPP0203_READ_REG1 -#define TCPP0203_READ_REG2 0x02U -#define TCPP0203_FLAG_REG TCPP0203_READ_REG2 - -/** - * @} - */ - -/************** Generic Function *******************/ - -typedef int32_t (*TCPP0203_Write_Func)(const void *, uint8_t, uint8_t *, uint8_t); -typedef int32_t (*TCPP0203_Read_Func)(const void *, uint8_t, uint8_t *, uint8_t); - -typedef struct -{ - TCPP0203_Write_Func WriteReg; - TCPP0203_Read_Func ReadReg; - void *handle; -} TCPP0203_ctx_t; - -/******************************************************************************* - * Register : Generic - All - * Address : Generic - All - * Bit Group Name: None - * Permission : W - *******************************************************************************/ -int32_t tcpp0203_write_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length); -int32_t tcpp0203_read_reg(const TCPP0203_ctx_t *ctx, uint8_t reg, uint8_t *data, uint8_t length); - -#ifdef __cplusplus -} -#endif - -#endif /* TCPP0203_REG_H */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ diff --git a/hw/bsp/stm32n6/family.cmake b/hw/bsp/stm32n6/family.cmake index c2c634525..76763937e 100644 --- a/hw/bsp/stm32n6/family.cmake +++ b/hw/bsp/stm32n6/family.cmake @@ -6,6 +6,7 @@ set(ST_PREFIX stm32${ST_FAMILY}xx) set(ST_HAL_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver) set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis_device_${ST_FAMILY}) set(CMSIS_5 ${TOP}/lib/CMSIS_5) +set(ST_TCPP0203 ${TOP}/hw/mcu/st/stm32-tcpp0203) # include board specific include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) diff --git a/hw/bsp/stm32n6/family.mk b/hw/bsp/stm32n6/family.mk index d613e53d2..37087ed42 100644 --- a/hw/bsp/stm32n6/family.mk +++ b/hw/bsp/stm32n6/family.mk @@ -2,6 +2,7 @@ ST_FAMILY = n6 ST_PREFIX = stm32${ST_FAMILY}xx ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/${ST_PREFIX}_hal_driver +ST_TCPP0203 = hw/mcu/st/stm32-tcpp0203 UF2_FAMILY_ID = 0x6db66083 diff --git a/tools/get_deps.py b/tools/get_deps.py index b2699b88c..6a36ef35d 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -133,6 +133,9 @@ deps_optional = { 'hw/mcu/st/stm32-mfxstm32l152': ['https://github.com/STMicroelectronics/stm32-mfxstm32l152.git', '7f4389efee9c6a655b55e5df3fceef5586b35f9b', 'stm32h7'], + 'hw/mcu/st/stm32-tcpp0203': ['https://github.com/STMicroelectronics/stm32-tcpp0203.git', + '9918655bff176ac3046ccf378b5c7bbbc6a38d15', + 'stm32h7rs stm32n6'], 'hw/mcu/st/stm32c0xx_hal_driver': ['https://github.com/STMicroelectronics/stm32c0xx_hal_driver.git', '41253e2f1d7ae4a4d0c379cf63f5bcf71fcf8eb3', 'stm32c0'], From 2e231a7517180a486211681127891d41cdbd48ee Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jun 2025 15:57:56 +0700 Subject: [PATCH 216/382] doc update --- README.rst | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/README.rst b/README.rst index 0d6b147d9..f4dfb0831 100644 --- a/README.rst +++ b/README.rst @@ -183,15 +183,13 @@ Supported CPUs +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ | Sony | CXD56 | ✔ | ✖ | ✔ | cxd56 | | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ -| ST STM32 | F0 | ✔ | ✖ | ✖ | stm32_fsdev | | +| ST STM32 | F0, F3, L0, L1, L5, WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | | | +----+------------------------+--------+------+-----------+------------------------+-------------------+ | | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | | | | +------------------------+--------+------+-----------+------------------------+-------------------+ | | | 105, 107 | ✔ | ✔ | ✖ | dwc2 | | | +----+------------------------+--------+------+-----------+------------------------+-------------------+ -| | F2, F4, F7, H7 | ✔ | ✔ | ✔ | dwc2 | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | F3 | ✔ | ✖ | ✖ | stm32_fsdev | | +| | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | | | +-----------------------------+--------+------+-----------+------------------------+-------------------+ | | C0, G0, H5 | ✔ | | ✖ | stm32_fsdev | | | +-----------------------------+--------+------+-----------+------------------------+-------------------+ @@ -201,25 +199,19 @@ Supported CPUs | +----+------------------------+--------+------+-----------+------------------------+-------------------+ | | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | | | | +------------------------+--------+------+-----------+------------------------+-------------------+ -| | | 4x5, 4x6 | ✔ | ✔ | ✖ | dwc2 | | +| | | 4x5, 4x6, 4+ | ✔ | ✔ | ✖ | dwc2 | | | +----+------------------------+--------+------+-----------+------------------------+-------------------+ -| | L4+ | ✔ | ✔ | ✖ | dwc2 | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | L5 | ✔ | ✖ | ✖ | stm32_fsdev | | +| | N6 | ✔ | ✔ | ✔ | dwc2 | | | +----+------------------------+--------+------+-----------+------------------------+-------------------+ | | U5 | 535, 545 | ✔ | | ✖ | stm32_fsdev | | | | +------------------------+--------+------+-----------+------------------------+-------------------+ | | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | | | | +------------------------+--------+------+-----------+------------------------+-------------------+ | | | 59x,5Ax,5Fx,5Gx | ✔ | ✔ | ✔ | dwc2 | | -| +----+------------------------+--------+------+-----------+------------------------+-------------------+ -| | WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | | -+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ ++--------------+----+------------------------+--------+------+-----------+------------------------+-------------------+ | TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | | | +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | MSP432E4 | ✔ | | ✖ | musb | | -| +-----------------------------+--------+------+-----------+------------------------+-------------------+ -| | TM4C123 | ✔ | | ✖ | musb | | +| | MSP432E4, TM4C123 | ✔ | | ✖ | musb | | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ | ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ From 7d66a3e7758665138f495b5d9174c1874332ce1a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 12 Jun 2025 21:20:49 +0700 Subject: [PATCH 217/382] merge n6 and h7rs (same config) --- src/common/tusb_mcu.h | 11 +---------- src/portable/synopsys/dwc2/dwc2_stm32.h | 4 ++-- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 027446a85..2ee2132bf 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -312,7 +312,7 @@ #define TUP_USBIP_FSDEV_STM32 #define TUP_DCD_ENDPOINT_MAX 8 -#elif TU_CHECK_MCU(OPT_MCU_STM32H7RS) +#elif TU_CHECK_MCU(OPT_MCU_STM32H7RS, OPT_MCU_STM32N6) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 @@ -322,15 +322,6 @@ // MCU with on-chip HS Phy #define TUP_RHPORT_HIGHSPEED 1 -#elif TU_CHECK_MCU(OPT_MCU_STM32N6) - #define TUP_USBIP_DWC2 - #define TUP_USBIP_DWC2_STM32 - - #define TUP_DCD_ENDPOINT_MAX 9 - - // MCU with on-chip HS Phy - #define TUP_RHPORT_HIGHSPEED 2 - //--------------------------------------------------------------------+ // Sony //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 0c1f835a9..dc4251c29 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -79,8 +79,8 @@ extern "C" { #elif CFG_TUSB_MCU == OPT_MCU_STM32N6 #include "stm32n6xx.h" - #define EP_MAX_FS 6 - #define EP_FIFO_SIZE_FS 1280 + #define EP_MAX_FS 9 + #define EP_FIFO_SIZE_FS 4096 #define EP_MAX_HS 9 #define EP_FIFO_SIZE_HS 4096 From e84efd2771858b9f00d78824ccf8b1fade5f103c Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 25 Jan 2025 13:00:41 +0100 Subject: [PATCH 218/382] Add STM32 DWC2 cache support Signed-off-by: HiFiPhile --- src/common/tusb_mcu.h | 15 +++++ src/portable/synopsys/dwc2/dcd_dwc2.c | 2 +- src/portable/synopsys/dwc2/dwc2_stm32.h | 73 +++++++++++++++++++++++++ src/portable/synopsys/dwc2/hcd_dwc2.c | 2 +- 4 files changed, 90 insertions(+), 2 deletions(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 2ee2132bf..8b30c98cd 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -220,12 +220,23 @@ #define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS #endif + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT 1 + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT 1 + #define CFG_TUSB_MEM_DCACHE_LINE_SIZE 32 + #elif TU_CHECK_MCU(OPT_MCU_STM32H7) + #include "stm32h7xx.h" #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_STM32 #define TUP_DCD_ENDPOINT_MAX 9 + #if __CORTEX_M == 7 + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT 1 + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT 1 + #define CFG_TUSB_MEM_DCACHE_LINE_SIZE 32 + #endif + #elif TU_CHECK_MCU(OPT_MCU_STM32H5) #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_STM32 @@ -322,6 +333,10 @@ // MCU with on-chip HS Phy #define TUP_RHPORT_HIGHSPEED 1 + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT 1 + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT 1 + #define CFG_TUSB_MEM_DCACHE_LINE_SIZE 32 + //--------------------------------------------------------------------+ // Sony //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 5f86d6b76..f7e9aacfe 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -88,7 +88,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc //-------------------------------------------------------------------- // DMA //-------------------------------------------------------------------- -#if CFG_TUD_MEM_DCACHE_ENABLE +#if CFG_TUD_MEM_DCACHE_ENABLE && CFG_TUD_DWC2_DMA_ENABLE bool dcd_dcache_clean(const void* addr, uint32_t data_size) { TU_VERIFY(addr && data_size); return dwc2_dcache_clean(addr, data_size); diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index dc4251c29..f01d11fe8 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -279,6 +279,79 @@ static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { } } +//------------- DCache -------------// +#if (CFG_TUD_MEM_DCACHE_ENABLE && CFG_TUD_DWC2_DMA_ENABLE) || (CFG_TUH_MEM_DCACHE_ENABLE && CFG_TUH_DWC2_DMA_ENABLE) + +typedef struct +{ + uintptr_t start; + uintptr_t end; +} mem_region_t; + +// Can be used to define additional uncached regions +#ifndef CFG_DWC2_MEM_UNCACHED_REGIONS +#define CFG_DWC2_MEM_UNCACHED_REGIONS +#endif + +static mem_region_t uncached_regions[] = { + // DTCM (although USB DMA can't transfer to/from DTCM) +#if CFG_TUSB_MCU == OPT_MCU_STM32H7 + {.start = 0x20000000, .end = 0x2001FFFF}, +#elif CFG_TUSB_MCU == OPT_MCU_STM32H7RS + // DTCM (although USB DMA can't transfer to/from DTCM) + {.start = 0x20000000, .end = 0x2002FFFF}, +#elif CFG_TUSB_MCU == OPT_MCU_STM32F7 + // DTCM + {.start = 0x20000000, .end = 0x2000FFFF}, +#else +#error "Cache maintenance is not supported yet" +#endif + CFG_DWC2_MEM_UNCACHED_REGIONS +}; + +TU_ATTR_ALWAYS_INLINE static inline uint32_t round_up_to_cache_line_size(uint32_t size) { + if (size & (CFG_TUD_MEM_DCACHE_LINE_SIZE-1)) { + size = (size & ~(CFG_TUD_MEM_DCACHE_LINE_SIZE-1)) + CFG_TUD_MEM_DCACHE_LINE_SIZE; + } + return size; +} + +TU_ATTR_ALWAYS_INLINE static inline bool is_cache_mem(uintptr_t addr) { + for (unsigned int i = 0; i < TU_ARRAY_SIZE(uncached_regions); i++) { + if (addr >= uncached_regions[i].start && addr <= uncached_regions[i].end) + return false; + } + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_clean(void const* addr, uint32_t data_size) { + const uintptr_t addr32 = (uintptr_t) addr; + if (is_cache_mem(addr32)) { + data_size = round_up_to_cache_line_size(data_size); + SCB_CleanDCache_by_Addr((uint32_t *) addr32, (int32_t) data_size); + } + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_invalidate(void const* addr, uint32_t data_size) { + const uintptr_t addr32 = (uintptr_t) addr; + if (is_cache_mem(addr32)) { + data_size = round_up_to_cache_line_size(data_size); + SCB_InvalidateDCache_by_Addr((void*) addr32, (int32_t) data_size); + } + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline bool dwc2_dcache_clean_invalidate(void const* addr, uint32_t data_size) { + const uintptr_t addr32 = (uintptr_t) addr; + if (is_cache_mem(addr32)) { + data_size = round_up_to_cache_line_size(data_size); + SCB_CleanInvalidateDCache_by_Addr((uint32_t *) addr32, (int32_t) data_size); + } + return true; +} +#endif + #ifdef __cplusplus } #endif diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 257fa2833..6b48c2346 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -141,7 +141,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool dma_host_enabled(const dwc2_regs_t* dwc return CFG_TUH_DWC2_DMA_ENABLE && ghwcfg2.arch == GHWCFG2_ARCH_INTERNAL_DMA; } -#if CFG_TUH_MEM_DCACHE_ENABLE +#if CFG_TUH_MEM_DCACHE_ENABLE && CFG_TUH_DWC2_DMA_ENABLE bool hcd_dcache_clean(const void* addr, uint32_t data_size) { TU_VERIFY(addr && data_size); return dwc2_dcache_clean(addr, data_size); From e19ff3ecae3b5a04756749a3d8496e6284f37d85 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 13 Jun 2025 13:17:41 +0200 Subject: [PATCH 219/382] Add cache line size alignment to buffer macro Signed-off-by: HiFiPhile --- src/common/tusb_types.h | 12 ++++++------ src/tusb_option.h | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index fd7f01b67..2099e1af8 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -36,39 +36,39 @@ #endif //------------- Device DCache declaration -------------// -#define TUD_EPBUF_DCACHE_SIZE(_size) (CFG_TUD_MEM_DCACHE_ENABLE ? \ +#define TUD_EPBUF_DCACHE_SIZE(_size) (TUD_EPBUF_DCACHE_ALIGNED ? \ (TU_DIV_CEIL(_size, CFG_TUD_MEM_DCACHE_LINE_SIZE) * CFG_TUD_MEM_DCACHE_LINE_SIZE) : (_size)) // Declare an endpoint buffer with uint8_t[size] #define TUD_EPBUF_DEF(_name, _size) \ union { \ CFG_TUD_MEM_ALIGN uint8_t _name[_size]; \ - uint8_t _name##_dcache_padding[TUD_EPBUF_DCACHE_SIZE(_size)]; \ + TU_ATTR_ALIGNED(TUD_EPBUF_DCACHE_ALIGNED ? CFG_TUD_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUD_EPBUF_DCACHE_SIZE(_size)]; \ } // Declare an endpoint buffer with a type #define TUD_EPBUF_TYPE_DEF(_type, _name) \ union { \ CFG_TUD_MEM_ALIGN _type _name; \ - uint8_t _name##_dcache_padding[TUD_EPBUF_DCACHE_SIZE(sizeof(_type))]; \ + TU_ATTR_ALIGNED(TUD_EPBUF_DCACHE_ALIGNED ? CFG_TUD_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUD_EPBUF_DCACHE_SIZE(sizeof(_type))]; \ } //------------- Host DCache declaration -------------// -#define TUH_EPBUF_DCACHE_SIZE(_size) (CFG_TUH_MEM_DCACHE_ENABLE ? \ +#define TUH_EPBUF_DCACHE_SIZE(_size) (TUH_EPBUF_DCACHE_ALIGNED ? \ (TU_DIV_CEIL(_size, CFG_TUH_MEM_DCACHE_LINE_SIZE) * CFG_TUH_MEM_DCACHE_LINE_SIZE) : (_size)) // Declare an endpoint buffer with uint8_t[size] #define TUH_EPBUF_DEF(_name, _size) \ union { \ CFG_TUH_MEM_ALIGN uint8_t _name[_size]; \ - uint8_t _name##_dcache_padding[TUH_EPBUF_DCACHE_SIZE(_size)]; \ + TU_ATTR_ALIGNED(TUH_EPBUF_DCACHE_ALIGNED ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUH_EPBUF_DCACHE_SIZE(_size)]; \ } // Declare an endpoint buffer with a type #define TUH_EPBUF_TYPE_DEF(_type, _name) \ union { \ CFG_TUH_MEM_ALIGN _type _name; \ - uint8_t _name##_dcache_padding[TUH_EPBUF_DCACHE_SIZE(sizeof(_type))]; \ + TU_ATTR_ALIGNED(TUH_EPBUF_DCACHE_ALIGNED ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUH_EPBUF_DCACHE_SIZE(sizeof(_type))]; \ } diff --git a/src/tusb_option.h b/src/tusb_option.h index cca6096c6..42c2e650f 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -465,6 +465,13 @@ #define CFG_TUD_MEM_DCACHE_LINE_SIZE CFG_TUSB_MEM_DCACHE_LINE_SIZE #endif +#if CFG_TUD_MEM_DCACHE_ENABLE && \ + (CFG_TUD_DWC2_DMA_ENABLE || defined(TUP_USBIP_CHIPIDEA_HS)) + #define TUD_EPBUF_DCACHE_ALIGNED 1 +#else + #define TUD_EPBUF_DCACHE_ALIGNED 0 +#endif + #ifndef CFG_TUD_ENDPOINT0_SIZE #define CFG_TUD_ENDPOINT0_SIZE 64 #endif @@ -584,6 +591,13 @@ #define CFG_TUH_MEM_DCACHE_LINE_SIZE CFG_TUSB_MEM_DCACHE_LINE_SIZE #endif +#if CFG_TUH_MEM_DCACHE_ENABLE && \ + (CFG_TUH_DWC2_DMA_ENABLE || defined(TUP_USBIP_CHIPIDEA_HS)) + #define TUH_EPBUF_DCACHE_ALIGNED 1 +#else + #define TUH_EPBUF_DCACHE_ALIGNED 0 +#endif + //------------- CLASS -------------// #ifndef CFG_TUH_HUB From 37316e057d811767f63427ab619cfb08e844ec75 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 25 Jan 2025 13:02:08 +0100 Subject: [PATCH 220/382] hw/h7rs: Enable D-Cache in BSP Signed-off-by: HiFiPhile --- hw/bsp/stm32f7/family.c | 5 +++++ hw/bsp/stm32h7/family.c | 5 +++++ hw/bsp/stm32h7rs/family.c | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/hw/bsp/stm32f7/family.c b/hw/bsp/stm32f7/family.c index 5f63834d0..b82ab7d51 100644 --- a/hw/bsp/stm32f7/family.c +++ b/hw/bsp/stm32f7/family.c @@ -78,6 +78,11 @@ void OTG_HS_IRQHandler(void) { //--------------------------------------------------------------------+ void board_init(void) { + SCB_EnableICache(); + SCB_EnableDCache(); + + HAL_Init(); + board_clock_init(); // Enable All GPIOs clocks diff --git a/hw/bsp/stm32h7/family.c b/hw/bsp/stm32h7/family.c index f8723b0c7..23bfcb90e 100644 --- a/hw/bsp/stm32h7/family.c +++ b/hw/bsp/stm32h7/family.c @@ -98,6 +98,11 @@ static void trace_etm_init(void) { #endif void board_init(void) { + SCB_EnableICache(); + SCB_EnableDCache(); + + HAL_Init(); + // Implemented in board.h SystemClock_Config(); diff --git a/hw/bsp/stm32h7rs/family.c b/hw/bsp/stm32h7rs/family.c index 4b81deea0..b6b2d70e9 100644 --- a/hw/bsp/stm32h7rs/family.c +++ b/hw/bsp/stm32h7rs/family.c @@ -124,9 +124,13 @@ void log_swo_init(void) #endif void board_init(void) { + SCB_EnableICache(); + SCB_EnableDCache(); + HAL_Init(); HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY); + // Implemented in board.h SystemClock_Config(); From 424d74373981a75d127889866848bb4aef7a46a6 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 31 Jan 2025 23:52:01 +0100 Subject: [PATCH 221/382] hw/h7rs: Update linker to put RTT in DTCM Signed-off-by: HiFiPhile --- .../boards/stm32h7s3nucleo/board.cmake | 2 -- .../stm32h7rs/boards/stm32h7s3nucleo/board.mk | 4 --- hw/bsp/stm32h7rs/family.cmake | 7 +++-- hw/bsp/stm32h7rs/family.mk | 7 +++-- .../stm32h7s3xx_flash.icf | 6 ++--- .../stm32h7s3xx_flash.ld | 26 ++++++++++++------- 6 files changed, 25 insertions(+), 27 deletions(-) rename hw/bsp/stm32h7rs/{boards/stm32h7s3nucleo => linker}/stm32h7s3xx_flash.icf (93%) rename hw/bsp/stm32h7rs/{boards/stm32h7s3nucleo => linker}/stm32h7s3xx_flash.ld (86%) diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake index f52b70408..aae820aee 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.cmake @@ -1,9 +1,7 @@ set(MCU_VARIANT stm32h7s3xx) set(JLINK_DEVICE stm32h7s3xx) -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/stm32h7s3xx_flash.ld) set(LD_FILE_Clang ${LD_FILE_GNU}) -set(LD_FILE_IAR ${CMAKE_CURRENT_LIST_DIR}/stm32h7s3xx_flash.icf) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk index cf0c2ff54..47055a108 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.mk @@ -7,10 +7,6 @@ JLINK_DEVICE = stm32h7s3xx # flash target using on-board stlink flash: flash-stlink -# Linker -LD_FILE_GCC = $(BOARD_PATH)/stm32h7s3xx_flash.ld -LD_FILE_IAR = $(BOARD_PATH)/stm32h7s3xx_flash.icf - SRC_C += \ $(ST_TCPP0203)/tcpp0203.c \ $(ST_TCPP0203)/tcpp0203_reg.c \ diff --git a/hw/bsp/stm32h7rs/family.cmake b/hw/bsp/stm32h7rs/family.cmake index e5e98f914..e70d37777 100644 --- a/hw/bsp/stm32h7rs/family.cmake +++ b/hw/bsp/stm32h7rs/family.cmake @@ -54,11 +54,11 @@ function(add_board_target BOARD_TARGET) set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) if(NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_flash.ld) + set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT}_flash.ld) endif() set(LD_FILE_Clang ${LD_FILE_GNU}) if(NOT DEFINED LD_FILE_IAR) - set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf) + set(LD_FILE_IAR ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${MCU_VARIANT}_flash.icf) endif() add_library(${BOARD_TARGET} STATIC @@ -87,8 +87,7 @@ function(add_board_target BOARD_TARGET) BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} BOARD_TUH_RHPORT=${RHPORT_HOST} BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} - SEGGER_RTT_SECTION="noncacheable_buffer" - BUFFER_SIZE_UP=0x3000 + SEGGER_RTT_SECTION=\"dtcm_data\" ) update_board(${BOARD_TARGET}) diff --git a/hw/bsp/stm32h7rs/family.mk b/hw/bsp/stm32h7rs/family.mk index 9970059f8..c60a5c00d 100644 --- a/hw/bsp/stm32h7rs/family.mk +++ b/hw/bsp/stm32h7rs/family.mk @@ -43,8 +43,7 @@ CFLAGS += \ -DBOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} \ -DBOARD_TUH_RHPORT=${RHPORT_HOST} \ -DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} \ - -DSEGGER_RTT_SECTION=\"noncacheable_buffer\" \ - -DBUFFER_SIZE_UP=0x3000 \ + -DSEGGER_RTT_SECTION="dtcm_data" \ # GCC Flags CFLAGS_GCC += \ @@ -91,5 +90,5 @@ SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_$(MCU_VARIANT).s SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT).s # Linker -LD_FILE_GCC ?= $(ST_CMSIS)/Source/Templates/gcc/linker/$(MCU_VARIANT)_flash.ld -LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash.icf +LD_FILE_GCC ?= $(FAMILY_PATH)/linker/$(MCU_VARIANT)_flash.ld +LD_FILE_IAR ?= $(FAMILY_PATH)/linker/$(MCU_VARIANT)_flash.icf diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf b/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.icf similarity index 93% rename from hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf rename to hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.icf index 8ffaa74a7..8398fa07b 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.icf +++ b/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.icf @@ -4,7 +4,7 @@ /*-Specials-*/ define symbol __ICFEDIT_intvec_start__ = 0x08000000; /*-Memory Regions-*/ -define symbol NONCACHEABLEBUFFER_size = 0x4000; +define symbol NONCACHEABLEBUFFER_size = 0x400; define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; define symbol __ICFEDIT_region_ROM_end__ = 0x0800FFFF; define symbol __ICFEDIT_region_RAM_start__ = 0x24000000; @@ -14,7 +14,7 @@ define symbol NONCACHEABLEBUFFER_end = __ICFEDIT_region_RAM_end__ + NONCAC /*-Sizes-*/ -define symbol __ICFEDIT_size_cstack__ = 0x800; +define symbol __ICFEDIT_size_cstack__ = 0x400; define symbol __ICFEDIT_size_heap__ = 0x200; /**** End of ICF editor section. ###ICF###*/ @@ -51,5 +51,5 @@ place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; place in ROM_region { readonly }; place in RAM_region { readwrite }; +place in DTCM_region { block CSTACK, block HEAP, section dtcm_data }; place in NONCACHEABLE_region { section noncacheable_buffer }; -place in DTCM_region { block CSTACK, block HEAP }; diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld b/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld similarity index 86% rename from hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld rename to hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld index 3bd7f0b89..86acf9742 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/stm32h7s3xx_flash.ld +++ b/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld @@ -35,15 +35,19 @@ /* Entry Point */ ENTRY(Reset_Handler) +/* Highest address of the user mode stack */ +_estack = ORIGIN(DTCM) + LENGTH(DTCM); /* end of "DTCM" Ram type memory */ + _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ __FLASH_BEGIN = 0x08000000; __FLASH_SIZE = 0x00010000; + __RAM_BEGIN = 0x24000000; __RAM_SIZE = 0x4FC00; -__RAM_NONCACHEABLEBUFFER_SIZE = 0x4000; +__RAM_NONCACHEABLEBUFFER_SIZE = 0x400; /* Memories definition */ MEMORY @@ -59,9 +63,6 @@ MEMORY FLASH (xrw) : ORIGIN = __FLASH_BEGIN, LENGTH = __FLASH_SIZE } -/* Highest address of the user mode stack */ -_estack = ORIGIN(DTCM) + LENGTH(DTCM); /* end of "DTCM" Ram type memory */ - /* Sections */ SECTIONS { @@ -99,14 +100,14 @@ SECTIONS . = ALIGN(4); } >FLASH - .ARM.extab : + .ARM.extab (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ { . = ALIGN(4); *(.ARM.extab* .gnu.linkonce.armextab.*) . = ALIGN(4); } >FLASH - .ARM : + .ARM (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ { . = ALIGN(4); __exidx_start = .; @@ -115,7 +116,7 @@ SECTIONS . = ALIGN(4); } >FLASH - .preinit_array : + .preinit_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ { . = ALIGN(4); PROVIDE_HIDDEN (__preinit_array_start = .); @@ -124,7 +125,7 @@ SECTIONS . = ALIGN(4); } >FLASH - .init_array : + .init_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ { . = ALIGN(4); PROVIDE_HIDDEN (__init_array_start = .); @@ -134,7 +135,7 @@ SECTIONS . = ALIGN(4); } >FLASH - .fini_array : + .fini_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ { . = ALIGN(4); PROVIDE_HIDDEN (__fini_array_start = .); @@ -182,7 +183,7 @@ SECTIONS { __NONCACHEABLEBUFFER_BEGIN = .;/* create symbol for start of section */ KEEP(*(noncacheable_buffer)) - __NONCACHEABLEBUFFER_END = .; /* create symbol for start of section */ + __NONCACHEABLEBUFFER_END = .; /* create symbol for end of section */ } > RAM_NONCACHEABLEBUFFER /* User_heap_stack section, used to check that there is enough "DTCM" Ram type memory left */ @@ -196,6 +197,11 @@ SECTIONS . = ALIGN(8); } >DTCM + .dtcm_data : + { + *(dtcm_data) + } >DTCM + /* Remove information from the compiler libraries */ /DISCARD/ : { From ea02e929b4daafb28be30b08609a6f68f64e2a0d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 13 Jun 2025 18:44:05 +0200 Subject: [PATCH 222/382] audio: buffer macro update Signed-off-by: HiFiPhile --- src/class/audio/audio_device.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 11a3d4a73..dc45a72bc 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -109,14 +109,14 @@ // Put swap buffer in USB section only if necessary #if USE_LINEAR_BUFFER - #define IN_SW_BUF_MEM_ATTR TU_ATTR_ALIGNED(4) + #define IN_SW_BUF_MEM_ATTR #else - #define IN_SW_BUF_MEM_ATTR CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN + #define IN_SW_BUF_MEM_ATTR CFG_TUD_MEM_SECTION #endif #if USE_LINEAR_BUFFER - #define OUT_SW_BUF_MEM_ATTR TU_ATTR_ALIGNED(4) + #define OUT_SW_BUF_MEM_ATTR #else - #define OUT_SW_BUF_MEM_ATTR CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN + #define OUT_SW_BUF_MEM_ATTR CFG_TUD_MEM_SECTION #endif // EP IN software buffers and mutexes From 76a6834659e50f50bfff39febb62ec67be25d581 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 2 Jun 2024 14:04:54 +0200 Subject: [PATCH 223/382] USBD: introduce xfer_isr. --- src/device/usbd.c | 35 ++++++++++++++++++++++++++++++++++- src/device/usbd_pvt.h | 1 + 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 6e5fcf3b6..ae18792c5 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -163,6 +163,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = cdcd_open, .control_xfer_cb = cdcd_control_xfer_cb, .xfer_cb = cdcd_xfer_cb, + .xfer_isr = NULL, .sof = NULL }, #endif @@ -176,6 +177,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = mscd_open, .control_xfer_cb = mscd_control_xfer_cb, .xfer_cb = mscd_xfer_cb, + .xfer_isr = NULL, .sof = NULL }, #endif @@ -189,6 +191,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = hidd_open, .control_xfer_cb = hidd_control_xfer_cb, .xfer_cb = hidd_xfer_cb, + .xfer_isr = NULL, .sof = NULL }, #endif @@ -202,6 +205,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = audiod_open, .control_xfer_cb = audiod_control_xfer_cb, .xfer_cb = audiod_xfer_cb, + .xfer_isr = NULL, .sof = audiod_sof_isr }, #endif @@ -215,6 +219,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = videod_open, .control_xfer_cb = videod_control_xfer_cb, .xfer_cb = videod_xfer_cb, + .xfer_isr = NULL, .sof = NULL }, #endif @@ -228,6 +233,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .reset = midid_reset, .control_xfer_cb = midid_control_xfer_cb, .xfer_cb = midid_xfer_cb, + .xfer_isr = NULL, .sof = NULL }, #endif @@ -241,6 +247,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = vendord_open, .control_xfer_cb = tud_vendor_control_xfer_cb, .xfer_cb = vendord_xfer_cb, + .xfer_isr = NULL, .sof = NULL }, #endif @@ -254,6 +261,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = usbtmcd_open_cb, .control_xfer_cb = usbtmcd_control_xfer_cb, .xfer_cb = usbtmcd_xfer_cb, + .xfer_isr = NULL, .sof = NULL }, #endif @@ -267,6 +275,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = dfu_rtd_open, .control_xfer_cb = dfu_rtd_control_xfer_cb, .xfer_cb = NULL, + .xfer_isr = NULL, .sof = NULL }, #endif @@ -280,6 +289,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = dfu_moded_open, .control_xfer_cb = dfu_moded_control_xfer_cb, .xfer_cb = NULL, + .xfer_isr = NULL, .sof = NULL }, #endif @@ -293,7 +303,8 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = netd_open, .control_xfer_cb = netd_control_xfer_cb, .xfer_cb = netd_xfer_cb, - .sof = NULL, + .xfer_isr = NULL, + .sof = NULL, }, #endif @@ -306,6 +317,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = btd_open, .control_xfer_cb = btd_control_xfer_cb, .xfer_cb = btd_xfer_cb, + .xfer_isr = NULL, .sof = NULL }, #endif @@ -1231,6 +1243,27 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) send = true; break; + case DCD_EVENT_XFER_COMPLETE: + { + send = true; + // Invoke the class callback associated with the endpoint address + uint8_t const ep_addr = event->xfer_complete.ep_addr; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const ep_dir = tu_edpt_dir(ep_addr); + + if(epnum > 0) { + usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]); + + if (driver && driver->xfer_isr) { + _usbd_dev.ep_status[epnum][ep_dir].busy = 0; + _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; + + send = !driver->xfer_isr(event->rhport, ep_addr, (xfer_result_t) event->xfer_complete.result, event->xfer_complete.len); + } + } + break; + } + default: send = true; break; diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 5c6f9dbee..40622be66 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -57,6 +57,7 @@ typedef struct { uint16_t (* open ) (uint8_t rhport, tusb_desc_interface_t const * desc_intf, uint16_t max_len); bool (* control_xfer_cb ) (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); bool (* xfer_cb ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + bool (* xfer_isr ) (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); // optional void (* sof ) (uint8_t rhport, uint32_t frame_count); // optional } usbd_class_driver_t; From eed294fbb58257f56b0fb59284624e50f43fa8a4 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 14 Jun 2025 19:39:02 +0200 Subject: [PATCH 224/382] audio: move ISO transfers into xfer_isr Signed-off-by: HiFiPhile --- src/class/audio/audio_device.c | 154 +++++++++++++-------------------- src/class/audio/audio_device.h | 13 +-- src/device/usbd.c | 2 +- 3 files changed, 67 insertions(+), 102 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 11a3d4a73..4c8a69ee1 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -371,35 +371,19 @@ typedef struct //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_ENABLE_EP_IN -TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting) { +TU_ATTR_WEAK bool tud_audio_tx_done_isr(uint8_t rhport, uint16_t n_bytes_sent, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting) { (void) rhport; + (void) n_bytes_sent; (void) func_id; (void) ep_in; (void) cur_alt_setting; return true; } -TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting) { - (void) rhport; - (void) n_bytes_copied; - (void) func_id; - (void) ep_in; - (void) cur_alt_setting; - return true; -} #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT -TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting) { - (void) rhport; - (void) n_bytes_received; - (void) func_id; - (void) ep_out; - (void) cur_alt_setting; - return true; -} - -TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting) { +TU_ATTR_WEAK bool tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting) { (void) rhport; (void) n_bytes_received; (void) func_id; @@ -410,10 +394,6 @@ TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_byte #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -TU_ATTR_WEAK void tud_audio_fb_done_cb(uint8_t func_id) { - (void) func_id; -} - TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t *feedback_param) { (void) func_id; (void) alt_itf; @@ -433,7 +413,7 @@ TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func #endif #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP -TU_ATTR_WEAK void tud_audio_int_done_cb(uint8_t rhport) { +TU_ATTR_WEAK void tud_audio_int_xfer_cb(uint8_t rhport) { (void) rhport; } #endif @@ -509,11 +489,11 @@ TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_reque tu_static CFG_TUD_MEM_SECTION audiod_function_t _audiod_fct[CFG_TUD_AUDIO]; #if CFG_TUD_AUDIO_ENABLE_EP_OUT -static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t *audio, uint16_t n_bytes_received); +static bool audiod_rx_xfer_isr(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received); #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN -static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t *audio); +static bool audiod_tx_xfer_isr(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_sent); #endif static bool audiod_get_interface(uint8_t rhport, tusb_control_request_t const *p_request); @@ -570,18 +550,13 @@ tu_fifo_t *tud_audio_n_get_ep_out_ff(uint8_t func_id) { return NULL; } -// This function is called once an audio packet is received by the USB and is responsible for putting data from USB memory into EP_OUT_FIFO. -static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t *audio, uint16_t n_bytes_received) { - uint8_t idxItf = 0; +static bool audiod_rx_xfer_isr(uint8_t rhport, audiod_function_t* audio, uint16_t n_bytes_received) { + uint8_t idxItf; uint8_t const *dummy2; - uint8_t idx_audio_fct = 0; - idx_audio_fct = audiod_get_audio_fct_idx(audio); + uint8_t idx_audio_fct = audiod_get_audio_fct_idx(audio); TU_VERIFY(audiod_get_AS_interface_index(audio->ep_out_as_intf_num, audio, &idxItf, &dummy2)); - // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO - TU_VERIFY(tud_audio_rx_done_pre_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); - #if USE_LINEAR_BUFFER_RX // Data currently is in linear buffer, copy into EP OUT FIFO TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); @@ -599,8 +574,8 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t *audio, uint16_t } #endif - // Call a weak callback here - a possibility for user to get informed decoding was completed - TU_VERIFY(tud_audio_rx_done_post_read_cb(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); + // Call a weak callback here - a possibility for user to get informed an audio packet was received and data gets now loaded into EP FIFO + TU_VERIFY(tud_audio_rx_done_isr(rhport, n_bytes_received, idx_audio_fct, audio->ep_out, audio->alt_setting[idxItf])); return true; } @@ -613,17 +588,6 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t *audio, uint16_t #if CFG_TUD_AUDIO_ENABLE_EP_IN -/** - * \brief Write data to EP in buffer - * - * Write data to buffer. If it is full, new data can be inserted once a transmit was scheduled. See audiod_tx_done_cb(). - * If TX FIFOs are used, this function is not available in order to not let the user mess up the encoding process. - * - * \param[in] func_id: Index of audio function interface - * \param[in] data: Pointer to data array to be copied from - * \param[in] len: # of array elements to copy - * \return Number of bytes actually written - */ uint16_t tud_audio_n_write(uint8_t func_id, const void *data, uint16_t len) { TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); return tu_fifo_write_n(&_audiod_fct[func_id].ep_in_ff, data, len); @@ -640,9 +604,7 @@ tu_fifo_t *tud_audio_n_get_ep_in_ff(uint8_t func_id) { return NULL; } -// This function is called once a transmit of an audio packet was successfully completed. Here, we encode samples and place it in IN EP's buffer for next transmission. -// n_bytes_copied - Informs caller how many bytes were loaded. In case n_bytes_copied = 0, a ZLP is scheduled to inform host no data is available for current frame. -static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t *audio) { +static bool audiod_tx_xfer_isr(uint8_t rhport, audiod_function_t * audio, uint16_t n_bytes_sent) { uint8_t idxItf; uint8_t const *dummy2; @@ -652,15 +614,11 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t *audio) { // Only send something if current alternate interface is not 0 as in this case nothing is to be sent due to UAC2 specifications if (audio->alt_setting[idxItf] == 0) return false; - // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer (in case FIFOs are used) or - // if no FIFOs are used the user may use this call back to load its data into the EP IN buffer by use of tud_audio_n_write_ep_in_buffer(). - TU_VERIFY(tud_audio_tx_done_pre_load_cb(rhport, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); - // Send everything in ISO EP FIFO uint16_t n_bytes_tx; #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL - // packet_sz_tx is based on total packet size + // packet_sz_tx is based on total packet size, here we want size for each support buffer. n_bytes_tx = audiod_tx_packet_size(audio->packet_sz_tx, tu_fifo_count(&audio->ep_in_ff), audio->ep_in_ff.depth, audio->ep_in_sz); #else n_bytes_tx = tu_min16(tu_fifo_count(&audio->ep_in_ff), audio->ep_in_sz);// Limit up to max packet size, more can not be done for ISO @@ -673,8 +631,8 @@ static bool audiod_tx_done_cb(uint8_t rhport, audiod_function_t *audio) { TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, n_bytes_tx)); #endif - // Call a weak callback here - a possibility for user to get informed former TX was completed and how many bytes were loaded for the next frame - TU_VERIFY(tud_audio_tx_done_post_load_cb(rhport, n_bytes_tx, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); + // Call a weak callback here - a possibility for user to get informed former TX was completed and data gets now loaded into EP in buffer + TU_VERIFY(tud_audio_tx_done_isr(rhport, n_bytes_sent, idx_audio_fct, audio->ep_in, audio->alt_setting[idxItf])); return true; } @@ -1227,8 +1185,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p usbd_edpt_clear_stall(rhport, ep_addr); #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 0x00)// Check if usage is data EP - { + // Check if usage is data EP + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 0x00) { // Save address audio->ep_in = ep_addr; audio->ep_in_as_intf_num = itf; @@ -1238,15 +1196,19 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p #if CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL audiod_parse_flow_control_params(audio, p_desc_parse_for_params); #endif - // Schedule first transmit if alternate interface is not zero i.e. streaming is disabled - in case no sample data is available a ZLP is loaded - // It is necessary to trigger this here since the refill is done with an RX FIFO empty interrupt which can only trigger if something was in there - TU_VERIFY(audiod_tx_done_cb(rhport, &_audiod_fct[func_id])); + // Schedule first transmit if alternate interface is not zero, as sample data is available a ZLP is loaded + #if USE_LINEAR_BUFFER_TX + TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_in, audio->lin_buf_in, 0)); + #else + // Send everything in ISO EP FIFO + TU_VERIFY(usbd_edpt_xfer_fifo(rhport, audio->ep_in, &audio->ep_in_ff, 0)); + #endif } #endif// CFG_TUD_AUDIO_ENABLE_EP_IN #if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT)// Checking usage not necessary - { + // Checking usage not necessary + if (tu_edpt_dir(ep_addr) == TUSB_DIR_OUT) { // Save address audio->ep_out = ep_addr; audio->ep_out_as_intf_num = itf; @@ -1261,10 +1223,12 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p } #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1)// Check if usage is explicit data feedback - { + // Check if usage is explicit data feedback + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 1) { audio->ep_fb = ep_addr; audio->feedback.frame_shift = desc_ep->bInterval - 1; + // Schedule first feedback transmit + audiod_fb_send(audio); } #endif #endif// CFG_TUD_AUDIO_ENABLE_EP_OUT @@ -1507,12 +1471,11 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 (void) result; (void) xferred_bytes; + #if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP // Search for interface belonging to given end point address and proceed as required for (uint8_t func_id = 0; func_id < CFG_TUD_AUDIO; func_id++) { audiod_function_t *audio = &_audiod_fct[func_id]; -#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP - // Data transmission of control interrupt finished if (audio->ep_int == ep_addr) { // According to USB2 specification, maximum payload of interrupt EP is 8 bytes on low speed, 64 bytes on full speed, and 1024 bytes on high speed (but only if an alternate interface other than 0 is used - see specification p. 49) @@ -1522,16 +1485,34 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // I assume here, that things above are handled by PHY // All transmission is done - what remains to do is to inform job was completed - tud_audio_int_done_cb(rhport); + tud_audio_int_xfer_cb(rhport); return true; } -#endif + } + #else + (void) rhport; + (void) ep_addr; + #endif + + return false; +} + +bool audiod_xfer_isr(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void) result; + (void) xferred_bytes; + + // Search for interface belonging to given end point address and proceed as required + for (uint8_t func_id = 0; func_id < CFG_TUD_AUDIO; func_id++) + { + audiod_function_t* audio = &_audiod_fct[func_id]; #if CFG_TUD_AUDIO_ENABLE_EP_IN // Data transmission of audio packet finished - if (audio->ep_in == ep_addr && audio->alt_setting != 0) { + if (audio->ep_in == ep_addr && audio->alt_setting != 0) + { // USB 2.0, section 5.6.4, third paragraph, states "An isochronous endpoint must specify its required bus access period. However, an isochronous endpoint must be prepared to handle poll rates faster than the one specified." // That paragraph goes on to say "An isochronous IN endpoint must return a zero-length packet whenever data is requested at a faster interval than the specified interval and data is not available." // This can only be solved reliably if we load a ZLP after every IN transmission since we can not say if the host requests samples earlier than we declared! Once all samples are collected we overwrite the loaded ZLP. @@ -1541,32 +1522,25 @@ bool audiod_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint3 // This is the only place where we can fill something into the EPs buffer! // Load new data - TU_VERIFY(audiod_tx_done_cb(rhport, audio)); - - // Transmission of ZLP is done by audiod_tx_done_cb() + audiod_tx_xfer_isr(rhport, audio, (uint16_t) xferred_bytes); return true; } #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT - // New audio packet received - if (audio->ep_out == ep_addr) { - TU_VERIFY(audiod_rx_done_cb(rhport, audio, (uint16_t) xferred_bytes)); + if (audio->ep_out == ep_addr) + { + audiod_rx_xfer_isr(rhport, audio, (uint16_t) xferred_bytes); return true; } - - #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP // Transmission of feedback EP finished if (audio->ep_fb == ep_addr) { - tud_audio_fb_done_cb(func_id); - // Schedule a transmit with the new value if EP is not busy - if (usbd_edpt_claim(rhport, audio->ep_fb)) { - // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent - return audiod_fb_send(audio); - } + // Schedule next transmission - value is changed bytud_audio_n_fb_set() in the meantime or the old value gets sent + audiod_fb_send(audio); + return true; } #endif #endif @@ -1627,11 +1601,6 @@ static void audiod_fb_fifo_count_update(audiod_function_t *audio, uint16_t lvl_n if (feedback > audio->feedback.max_value) feedback = audio->feedback.max_value; if (feedback < audio->feedback.min_value) feedback = audio->feedback.min_value; audio->feedback.value = feedback; - - // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (usbd_edpt_claim(audio->rhport, audio->ep_fb)) { - audiod_fb_send(audio); - } } uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) { @@ -1673,11 +1642,6 @@ bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback) { _audiod_fct[func_id].feedback.value = feedback; - // Schedule a transmit with the new value if EP is not busy - this triggers repetitive scheduling of the feedback value - if (usbd_edpt_claim(_audiod_fct[func_id].rhport, _audiod_fct[func_id].ep_fb)) { - return audiod_fb_send(&_audiod_fct[func_id]); - } - return true; } #endif diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 603535b2a..e5724fc6a 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -280,18 +280,18 @@ bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_req //--------------------------------------------------------------------+ #if CFG_TUD_AUDIO_ENABLE_EP_IN -bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); -bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); +// Callback in ISR context, this function is called once a transmit of an audio packet was successfully completed. +// Normally this function is not needed, since the data transfer should be driven by audio clock (i.e. I2S clock), call tud_audio_write() in I2S receive callback. +bool tud_audio_tx_done_isr(uint8_t rhport, uint16_t n_bytes_sent, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT -bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); -bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); +// Callback in ISR context, this function is called once a receive of an audio packet was successfully completed. +// Normally this function is not needed, since the data transfer should be driven by audio clock (i.e. I2S clock), call tud_audio_read() in I2S transmit callback. +bool tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting); #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP -void tud_audio_fb_done_cb(uint8_t func_id); - // Note about feedback calculation // @@ -487,6 +487,7 @@ void audiod_reset (uint8_t rhport); uint16_t audiod_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); bool audiod_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +bool audiod_xfer_isr (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); void audiod_sof_isr (uint8_t rhport, uint32_t frame_count); #ifdef __cplusplus diff --git a/src/device/usbd.c b/src/device/usbd.c index ae18792c5..63519dcfd 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -205,7 +205,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = { .open = audiod_open, .control_xfer_cb = audiod_control_xfer_cb, .xfer_cb = audiod_xfer_cb, - .xfer_isr = NULL, + .xfer_isr = audiod_xfer_isr, .sof = audiod_sof_isr }, #endif From 1a36a1c1afefdf7e7d2def73d5fc64703aabe728 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 14 Jun 2025 16:53:18 +0200 Subject: [PATCH 225/382] audio: remove FIFO mutex, as audio streaming is always single producer single consumer Signed-off-by: HiFiPhile --- src/class/audio/audio_device.c | 46 ++-------------------------------- 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 4c8a69ee1..290561a27 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -119,7 +119,7 @@ #define OUT_SW_BUF_MEM_ATTR CFG_TUD_MEM_SECTION CFG_TUD_MEM_ALIGN #endif -// EP IN software buffers and mutexes +// EP IN software buffers #if CFG_TUD_AUDIO_ENABLE_EP_IN tu_static IN_SW_BUF_MEM_ATTR struct { #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 @@ -132,18 +132,6 @@ tu_static IN_SW_BUF_MEM_ATTR struct { TUD_EPBUF_DEF(buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ); #endif } ep_in_sw_buf; - - #if CFG_FIFO_MUTEX - #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 - tu_static osal_mutex_def_t ep_in_ff_mutex_wr_1; - #endif - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 - tu_static osal_mutex_def_t ep_in_ff_mutex_wr_2; - #endif - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 - tu_static osal_mutex_def_t ep_in_ff_mutex_wr_3; - #endif - #endif #endif// CFG_TUD_AUDIO_ENABLE_EP_IN // Linear buffer TX in case: @@ -162,7 +150,7 @@ tu_static CFG_TUD_MEM_SECTION struct { } lin_buf_in; #endif// CFG_TUD_AUDIO_ENABLE_EP_IN && USE_LINEAR_BUFFER -// EP OUT software buffers and mutexes +// EP OUT software buffers #if CFG_TUD_AUDIO_ENABLE_EP_OUT tu_static OUT_SW_BUF_MEM_ATTR struct { #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 @@ -175,18 +163,6 @@ tu_static OUT_SW_BUF_MEM_ATTR struct { TUD_EPBUF_DEF(buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ); #endif } ep_out_sw_buf; - - #if CFG_FIFO_MUTEX - #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 - tu_static osal_mutex_def_t ep_out_ff_mutex_rd_1; - #endif - #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 - tu_static osal_mutex_def_t ep_out_ff_mutex_rd_2; - #endif - #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 - tu_static osal_mutex_def_t ep_out_ff_mutex_rd_3; - #endif - #endif #endif// CFG_TUD_AUDIO_ENABLE_EP_OUT // Linear buffer RX in case: @@ -751,25 +727,16 @@ void audiod_init(void) { #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 case 0: tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_1), NULL); - #endif break; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 case 1: tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_2), NULL); - #endif break; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 case 2: tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_in_ff, osal_mutex_create(&ep_in_ff_mutex_wr_3), NULL); - #endif break; #endif } @@ -803,25 +770,16 @@ void audiod_init(void) { #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 case 0: tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_1)); - #endif break; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 case 1: tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_2)); - #endif break; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 case 2: tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&audio->ep_out_ff, NULL, osal_mutex_create(&ep_out_ff_mutex_rd_3)); - #endif break; #endif } From 19b5ec5fd9b5fb423ceacf24d542ebba7f805316 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 14 Jun 2025 19:20:11 +0200 Subject: [PATCH 226/382] bsp: fix NUCLEO-H7S3L8 button Signed-off-by: HiFiPhile --- hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.h b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.h index dfa77a8fb..4fb72cce8 100644 --- a/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.h +++ b/hw/bsp/stm32h7rs/boards/stm32h7s3nucleo/board.h @@ -61,7 +61,7 @@ static board_pindef_t board_pindef[] = { }, { // Button .port = GPIOC, - .pin_init = { .Pin = GPIO_PIN_13, .Mode = GPIO_MODE_INPUT, .Pull = GPIO_PULLDOWN, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0 }, + .pin_init = { .Pin = GPIO_PIN_13, .Mode = GPIO_MODE_INPUT, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0 }, .active_state = 1 }, { // UART TX From 545690c83435fc9e972a65a4e46539c88f2a2853 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 14 Jun 2025 19:37:10 +0200 Subject: [PATCH 227/382] audio: update examples Signed-off-by: HiFiPhile --- .../device/audio_4_channel_mic/src/main.c | 227 +++++--------- .../audio_4_channel_mic_freertos/src/main.c | 291 +++++++----------- examples/device/audio_test/src/main.c | 214 ++++++------- .../audio_test/src/plot_audio_samples.py | 4 +- examples/device/audio_test/src/tusb_config.h | 2 +- .../device/audio_test_freertos/src/main.c | 257 +++++++--------- .../src/plot_audio_samples.py | 4 +- .../audio_test_freertos/src/tusb_config.h | 2 +- .../device/audio_test_multi_rate/src/main.c | 286 +++++++---------- .../audio_test_multi_rate/src/tusb_config.h | 3 +- examples/device/cdc_uac2/skip.txt | 8 + examples/device/cdc_uac2/src/main.c | 3 +- examples/device/cdc_uac2/src/tusb_config.h | 11 +- examples/device/cdc_uac2/src/uac2_app.c | 51 ++- .../device/cdc_uac2/src/usb_descriptors.c | 69 ++++- examples/device/uac2_headset/src/main.c | 262 ++++++---------- .../device/uac2_headset/src/tusb_config.h | 4 +- examples/device/uac2_speaker_fb/src/main.c | 261 +++++++--------- 18 files changed, 839 insertions(+), 1120 deletions(-) create mode 100644 examples/device/cdc_uac2/skip.txt diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index f78e48f0c..9b169e77e 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -31,10 +31,10 @@ * $ python3 plot_audio_samples.py */ -#include -#include -#include #include +#include +#include +#include #include "bsp/board_api.h" #include "tusb.h" @@ -43,14 +43,14 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -#define AUDIO_SAMPLE_RATE CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE +#define AUDIO_SAMPLE_RATE CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE /* Blink pattern * - 250 ms : device not mounted * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -60,31 +60,29 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 -uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// +1 for master channel 0 uint32_t sampFreq; uint8_t clkValid; // Range states -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state -audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state +audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 -uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000]; +uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX * CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000]; void led_blinking_task(void); void audio_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); if (board_init_after_tusb) { @@ -101,25 +99,23 @@ int main(void) sampleFreqRng.subrange[0].bRes = 0; // Generate dummy data - uint16_t * p_buff = i2s_dummy_buffer; + uint16_t *p_buff = i2s_dummy_buffer; uint16_t dataVal = 0; - for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) - { + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE / 1000; cnt++) { // CH0 saw wave *p_buff++ = dataVal; // CH1 inverted saw wave - *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; - dataVal+= 32; + *p_buff++ = 3200 + AUDIO_SAMPLE_RATE / 1000 - dataVal; + dataVal += 32; // CH3 square wave - *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE / 1000 / 2) ? 3400 : 5000; // CH4 sinus wave - float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); - *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); + float t = 2 * 3.1415f * cnt / (AUDIO_SAMPLE_RATE / 1000); + *p_buff++ = (uint16_t) ((int16_t) (sinf(t) * 750) + 6000); } - while (1) - { - tud_task(); // tinyusb device task + while (1) { + tud_task();// tinyusb device task led_blinking_task(); audio_task(); } @@ -130,29 +126,25 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } @@ -160,15 +152,15 @@ void tud_resume_cb(void) // AUDIO Task //--------------------------------------------------------------------+ -void audio_task(void) -{ - // Yet to be filled - e.g. read audio from I2S buffer. - // Here we simulate a I2S receive callback every 1ms. +// This task simulates an audio receive callback, one frame is received every 1ms. +// We assume that the audio data is read from an I2S buffer. +// In a real application, this would be replaced with actual I2S receive callback. +void audio_task(void) { static uint32_t start_ms = 0; uint32_t curr_ms = board_millis(); - if ( start_ms == curr_ms ) return; // not enough time + if (start_ms == curr_ms) return;// not enough time start_ms = curr_ms; - tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); + tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); } //--------------------------------------------------------------------+ @@ -176,8 +168,7 @@ void audio_task(void) //--------------------------------------------------------------------+ // Invoked when audio class specific set request received for an EP -bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; (void) pBuff; @@ -189,14 +180,15 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) ep; + (void) channelNum; + (void) ctrlSel; + (void) ep; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific set request received for an interface -bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; (void) pBuff; @@ -208,14 +200,15 @@ bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) itf; + (void) channelNum; + (void) ctrlSel; + (void) itf; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; // Page 91 in UAC2 specification @@ -230,40 +223,37 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); // If request is for our feature unit - if ( entityID == 2 ) - { - switch ( ctrlSel ) - { + if (entityID == 2) { + switch (ctrlSel) { case AUDIO_FU_CTRL_MUTE: // Request uses format layout 1 TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; + mute[channelNum] = ((audio_control_cur_1_t *) pBuff)->bCur; TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); - return true; + return true; case AUDIO_FU_CTRL_VOLUME: // Request uses format layout 2 TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); - volume[channelNum] = (uint16_t) ((audio_control_cur_2_t*) pBuff)->bCur; + volume[channelNum] = (uint16_t) ((audio_control_cur_2_t *) pBuff)->bCur; TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); - return true; + return true; // Unknown/Unsupported control default: TU_BREAKPOINT(); - return false; + return false; } } - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an EP -bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -271,16 +261,17 @@ bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) ep; + (void) channelNum; + (void) ctrlSel; + (void) ep; // return tud_control_xfer(rhport, p_request, &tmp, 1); - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an interface -bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -288,14 +279,15 @@ bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) itf; + (void) channelNum; + (void) ctrlSel; + (void) itf; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -305,12 +297,9 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * uint8_t entityID = TU_U16_HIGH(p_request->wIndex); // Input terminal (Microphone input) - if (entityID == 1) - { - switch ( ctrlSel ) - { - case AUDIO_TE_CTRL_CONNECTOR: - { + if (entityID == 1) { + switch (ctrlSel) { + case AUDIO_TE_CTRL_CONNECTOR: { // The terminal connector control only has a get request with only the CUR attribute. audio_desc_channel_cluster_t ret; @@ -321,9 +310,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * TU_LOG2(" Get terminal connector\r\n"); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); - } - break; + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); + } break; // Unknown/Unsupported control selector default: @@ -333,10 +321,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } // Feature unit - if (entityID == 2) - { - switch ( ctrlSel ) - { + if (entityID == 2) { + switch (ctrlSel) { case AUDIO_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away // There does not exist a range parameter block for mute @@ -344,8 +330,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); case AUDIO_FU_CTRL_VOLUME: - switch ( p_request->bRequest ) - { + switch (p_request->bRequest) { case AUDIO_CS_REQ_CUR: TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); @@ -355,21 +340,21 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * // Copy values - only for testing - better is version below audio_control_range_2_n_t(1) - ret; + ret; ret.wNumSubRanges = 1; - ret.subrange[0].bMin = -90; // -90 dB - ret.subrange[0].bMax = 90; // +90 dB - ret.subrange[0].bRes = 1; // 1 dB steps + ret.subrange[0].bMin = -90;// -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); // Unknown/Unsupported control default: TU_BREAKPOINT(); return false; } - break; + break; // Unknown/Unsupported control default: @@ -379,14 +364,11 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } // Clock Source unit - if ( entityID == 4 ) - { - switch ( ctrlSel ) - { + if (entityID == 4) { + switch (ctrlSel) { case AUDIO_CS_CTRL_SAM_FREQ: // channelNum is always zero in this case - switch ( p_request->bRequest ) - { + switch (p_request->bRequest) { case AUDIO_CS_REQ_CUR: TU_LOG2(" Get Sample Freq.\r\n"); // Buffered control transfer is needed for IN flow control to work @@ -396,12 +378,12 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * TU_LOG2(" Get Sample Freq. range\r\n"); return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); - // Unknown/Unsupported control + // Unknown/Unsupported control default: TU_BREAKPOINT(); return false; } - break; + break; case AUDIO_CS_CTRL_CLK_VALID: // Only cur attribute exists for this request @@ -416,59 +398,20 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } TU_LOG2(" Unsupported entity: %d\r\n", entityID); - return false; // Yet not implemented -} - -bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void) rhport; - (void) itf; - (void) ep_in; - (void) cur_alt_setting; - - - // In read world application data flow is driven by I2S clock, - // both tud_audio_tx_done_pre_load_cb() & tud_audio_tx_done_post_load_cb() are hardly used. - // For example in your I2S receive callback: - // void I2S_Rx_Callback(int channel, const void* data, uint16_t samples) - // { - // tud_audio_write_support_ff(channel, data, samples * N_BYTES_PER_SAMPLE * N_CHANNEL_PER_FIFO); - // } - - return true; -} - -bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void) rhport; - (void) n_bytes_copied; - (void) itf; - (void) ep_in; - (void) cur_alt_setting; - - return true; -} - -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - (void) p_request; - - return true; + return false;// Yet not implemented } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) return;// not enough time start_ms += blink_interval_ms; board_led_write(led_state); - led_state = 1 - led_state; // toggle + led_state = 1 - led_state;// toggle } diff --git a/examples/device/audio_4_channel_mic_freertos/src/main.c b/examples/device/audio_4_channel_mic_freertos/src/main.c index 99278b5cc..3f82398a2 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/main.c +++ b/examples/device/audio_4_channel_mic_freertos/src/main.c @@ -31,10 +31,10 @@ * $ python3 plot_audio_samples.py */ -#include -#include -#include #include +#include +#include +#include #include "bsp/board_api.h" #include "tusb.h" @@ -43,38 +43,38 @@ // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" - #include "freertos/semphr.h" #include "freertos/queue.h" + #include "freertos/semphr.h" #include "freertos/task.h" #include "freertos/timers.h" - #define USBD_STACK_SIZE 4096 + #define USBD_STACK_SIZE 4096 #else #include "FreeRTOS.h" - #include "semphr.h" #include "queue.h" + #include "semphr.h" #include "task.h" #include "timers.h" // Increase stack size when debug log is enabled - #define USBD_STACK_SIZE (4*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) + #define USBD_STACK_SIZE (4 * configMINIMAL_STACK_SIZE / 2) * (CFG_TUSB_DEBUG ? 2 : 1) #endif -#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE -#define AUDIO_STACK_SIZE configMINIMAL_STACK_SIZE +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define AUDIO_STACK_SIZE configMINIMAL_STACK_SIZE //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -#define AUDIO_SAMPLE_RATE CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE +#define AUDIO_SAMPLE_RATE CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE /* Blink pattern * - 250 ms : device not mounted * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -82,13 +82,13 @@ enum { // static task #if configSUPPORT_STATIC_ALLOCATION -StackType_t blinky_stack[BLINKY_STACK_SIZE]; +StackType_t blinky_stack[BLINKY_STACK_SIZE]; StaticTask_t blinky_taskdef; -StackType_t usb_device_stack[USBD_STACK_SIZE]; +StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; -StackType_t audio_stack[AUDIO_STACK_SIZE]; +StackType_t audio_stack[AUDIO_STACK_SIZE]; StaticTask_t audio_taskdef; #endif @@ -96,25 +96,24 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 -uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// +1 for master channel 0 uint32_t sampFreq; uint8_t clkValid; // Range states -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state -audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state +audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data, 4 channels muxed together, buffer[0] for CH0, buffer[1] for CH1, buffer[2] for CH2, buffer[3] for CH3 -uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX*CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE/1000]; +uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX * CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000]; -void led_blinking_task(void* param); -void usb_device_task(void* param); -void audio_task(void* param); +void led_blinking_task(void *param); +void usb_device_task(void *param); +void audio_isr_task(void *param); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // Init values @@ -127,20 +126,19 @@ int main(void) sampleFreqRng.subrange[0].bRes = 0; // Generate dummy data - uint16_t * p_buff = i2s_dummy_buffer; + uint16_t *p_buff = i2s_dummy_buffer; uint16_t dataVal = 0; - for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE/1000; cnt++) - { + for (uint16_t cnt = 0; cnt < AUDIO_SAMPLE_RATE / 1000; cnt++) { // CH0 saw wave *p_buff++ = dataVal; // CH1 inverted saw wave - *p_buff++ = 3200 + AUDIO_SAMPLE_RATE/1000 - dataVal; - dataVal+= 32; + *p_buff++ = 3200 + AUDIO_SAMPLE_RATE / 1000 - dataVal; + dataVal += 32; // CH3 square wave - *p_buff++ = cnt < (AUDIO_SAMPLE_RATE/1000/2) ? 3400:5000; + *p_buff++ = cnt < (AUDIO_SAMPLE_RATE / 1000 / 2) ? 3400 : 5000; // CH4 sinus wave - float t = 2*3.1415f * cnt / (AUDIO_SAMPLE_RATE/1000); - *p_buff++ = (uint16_t)((int16_t)(sinf(t) * 750) + 6000); + float t = 2 * 3.1415f * cnt / (AUDIO_SAMPLE_RATE / 1000); + *p_buff++ = (uint16_t) ((int16_t) (sinf(t) * 750) + 6000); } #if configSUPPORT_STATIC_ALLOCATION @@ -148,44 +146,42 @@ int main(void) xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); // Create a task for tinyusb device stack - xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); + xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, usb_device_stack, &usb_device_taskdef); - // Create a task for audio - xTaskCreateStatic(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES-1, audio_stack, &audio_taskdef); + // Audio receive (I2S) ISR simulation + // To simulate a ISR the priority is set to the highest + xTaskCreateStatic(audio_isr_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, audio_stack, &audio_taskdef); #else xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); - xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); - xTaskCreate(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL); + xTaskCreate(audio_isr_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); #endif - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 - #if !TUSB_MCU_VENDOR_ESPRESSIF - vTaskStartScheduler(); - #endif +// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 +#if !TUSB_MCU_VENDOR_ESPRESSIF + vTaskStartScheduler(); +#endif return 0; } #if TUSB_MCU_VENDOR_ESPRESSIF -void app_main(void) -{ +void app_main(void) { main(); } #endif // USB Device Driver task // This top level thread process all usb events and invoke callbacks -void usb_device_task(void* param) -{ +void usb_device_task(void *param) { (void) param; // init device stack on configured roothub port // This should be called after scheduler/kernel is started. // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); if (board_init_after_tusb) { @@ -193,8 +189,7 @@ void usb_device_task(void* param) } // RTOS forever loop - while (1) - { + while (1) { // tinyusb device task tud_task(); } @@ -205,29 +200,25 @@ void usb_device_task(void* param) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } @@ -235,14 +226,14 @@ void tud_resume_cb(void) // AUDIO Task //--------------------------------------------------------------------+ -void audio_task(void* param) -{ +// This task simulates an audio receive ISR, one frame is received every 1ms. +// We assume that the audio data is read from an I2S buffer. +// In a real application, this would be replaced with actual I2S receive callback. +void audio_isr_task(void *param) { (void) param; - // Yet to be filled - e.g. read audio from I2S buffer. - // Here we simulate a I2S receive callback every 1ms. while (1) { vTaskDelay(1); - tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); + tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); } } @@ -251,8 +242,7 @@ void audio_task(void* param) //--------------------------------------------------------------------+ // Invoked when audio class specific set request received for an EP -bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; (void) pBuff; @@ -264,14 +254,15 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) ep; + (void) channelNum; + (void) ctrlSel; + (void) ep; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific set request received for an interface -bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; (void) pBuff; @@ -283,14 +274,15 @@ bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) itf; + (void) channelNum; + (void) ctrlSel; + (void) itf; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; // Page 91 in UAC2 specification @@ -305,40 +297,36 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); // If request is for our feature unit - if ( entityID == 2 ) - { - switch ( ctrlSel ) - { + if (entityID == 2) { + switch (ctrlSel) { case AUDIO_FU_CTRL_MUTE: // Request uses format layout 1 TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; + mute[channelNum] = ((audio_control_cur_1_t *) pBuff)->bCur; - TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); - return true; + TU_LOG1(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + return true; case AUDIO_FU_CTRL_VOLUME: // Request uses format layout 2 TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); - volume[channelNum] = ((audio_control_cur_2_t*) pBuff)->bCur; - - TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); - return true; + volume[channelNum] = ((audio_control_cur_2_t *) pBuff)->bCur; + TU_LOG1(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + return true; // Unknown/Unsupported control default: TU_BREAKPOINT(); - return false; + return false; } } - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an EP -bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -346,14 +334,15 @@ bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) ep; + (void) channelNum; + (void) ctrlSel; + (void) ep; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an interface -bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -361,14 +350,15 @@ bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) itf; + (void) channelNum; + (void) ctrlSel; + (void) itf; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -378,12 +368,9 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * uint8_t entityID = TU_U16_HIGH(p_request->wIndex); // Input terminal (Microphone input) - if (entityID == 1) - { - switch ( ctrlSel ) - { - case AUDIO_TE_CTRL_CONNECTOR: - { + if (entityID == 1) { + switch (ctrlSel) { + case AUDIO_TE_CTRL_CONNECTOR: { // The terminal connector control only has a get request with only the CUR attribute. audio_desc_channel_cluster_t ret; @@ -392,11 +379,10 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * ret.bmChannelConfig = 0; ret.iChannelNames = 0; - TU_LOG2(" Get terminal connector\r\n"); + TU_LOG1(" Get terminal connector\r\n"); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); - } - break; + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); + } break; // Unknown/Unsupported control selector default: @@ -406,43 +392,39 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } // Feature unit - if (entityID == 2) - { - switch ( ctrlSel ) - { + if (entityID == 2) { + switch (ctrlSel) { case AUDIO_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away // There does not exist a range parameter block for mute - TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); + TU_LOG1(" Get Mute of channel: %u\r\n", channelNum); return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); case AUDIO_FU_CTRL_VOLUME: - switch ( p_request->bRequest ) - { + switch (p_request->bRequest) { case AUDIO_CS_REQ_CUR: - TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); + TU_LOG1(" Get Volume of channel: %u\r\n", channelNum); return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); case AUDIO_CS_REQ_RANGE: - TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); + TU_LOG1(" Get Volume range of channel: %u\r\n", channelNum); // Copy values - only for testing - better is version below - audio_control_range_2_n_t(1) - ret; + audio_control_range_2_n_t(1) ret; ret.wNumSubRanges = 1; - ret.subrange[0].bMin = -90; // -90 dB - ret.subrange[0].bMax = 90; // +90 dB - ret.subrange[0].bRes = 1; // 1 dB steps + ret.subrange[0].bMin = -90;// -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); // Unknown/Unsupported control default: TU_BREAKPOINT(); return false; } - break; + break; // Unknown/Unsupported control default: @@ -452,33 +434,30 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } // Clock Source unit - if ( entityID == 4 ) - { - switch ( ctrlSel ) - { + if (entityID == 4) { + switch (ctrlSel) { case AUDIO_CS_CTRL_SAM_FREQ: // channelNum is always zero in this case - switch ( p_request->bRequest ) - { + switch (p_request->bRequest) { case AUDIO_CS_REQ_CUR: - TU_LOG2(" Get Sample Freq.\r\n"); + TU_LOG1(" Get Sample Freq.\r\n"); // Buffered control transfer is needed for IN flow control to work return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); case AUDIO_CS_REQ_RANGE: - TU_LOG2(" Get Sample Freq. range\r\n"); + TU_LOG1(" Get Sample Freq. range\r\n"); return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); - // Unknown/Unsupported control + // Unknown/Unsupported control default: TU_BREAKPOINT(); return false; } - break; + break; case AUDIO_CS_CTRL_CLK_VALID: // Only cur attribute exists for this request - TU_LOG2(" Get Sample Freq. valid\r\n"); + TU_LOG1(" Get Sample Freq. valid\r\n"); return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); // Unknown/Unsupported control @@ -488,52 +467,14 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } } - TU_LOG2(" Unsupported entity: %d\r\n", entityID); - return false; // Yet not implemented -} - -bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void) rhport; - (void) itf; - (void) ep_in; - (void) cur_alt_setting; - - - // In read world application data flow is driven by I2S clock, - // both tud_audio_tx_done_pre_load_cb() & tud_audio_tx_done_post_load_cb() are hardly used. - // For example in your I2S receive callback: - // void I2S_Rx_Callback(int channel, const void* data, uint16_t samples) - // { - // tud_audio_write_support_ff(channel, data, samples * N_BYTES_PER_SAMPLE * N_CHANNEL_PER_FIFO); - // } - - return true; -} - -bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void) rhport; - (void) n_bytes_copied; - (void) itf; - (void) ep_in; - (void) cur_alt_setting; - - return true; -} - -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void) rhport; - (void) p_request; - - return true; + TU_LOG1(" Unsupported entity: %d\r\n", entityID); + return false;// Yet not implemented } ///--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void* param) { +void led_blinking_task(void *param) { (void) param; static uint32_t start_ms = 0; static bool led_state = false; @@ -544,6 +485,6 @@ void led_blinking_task(void* param) { start_ms += blink_interval_ms; board_led_write(led_state); - led_state = 1 - led_state; // toggle + led_state = 1 - led_state;// toggle } } diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 018c48994..07728e24a 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -31,8 +31,8 @@ * $ python3 plot_audio_samples.py */ -#include #include +#include #include #include "bsp/board_api.h" @@ -47,7 +47,7 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -57,32 +57,30 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 -uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// +1 for master channel 0 uint32_t sampFreq; uint8_t clkValid; // Range states -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state -audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state +audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data -uint16_t test_buffer_audio[(CFG_TUD_AUDIO_EP_SZ_IN - 2) / 2]; +uint16_t test_buffer_audio[CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / 2]; uint16_t startVal = 0; void led_blinking_task(void); void audio_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); if (board_init_after_tusb) { @@ -98,9 +96,8 @@ int main(void) sampleFreqRng.subrange[0].bMax = CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE; sampleFreqRng.subrange[0].bRes = 0; - while (1) - { - tud_task(); // tinyusb device task + while (1) { + tud_task();// tinyusb device task led_blinking_task(); audio_task(); } @@ -111,40 +108,45 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } + //--------------------------------------------------------------------+ // AUDIO Task //--------------------------------------------------------------------+ -void audio_task(void) -{ - // Yet to be filled - e.g. put meas data into TX FIFOs etc. - // asm("nop"); +// This task simulates an audio receive callback, one frame is received every 1ms. +// We assume that the audio data is read from an I2S buffer. +// In a real application, this would be replaced with actual I2S receive callback. +void audio_task(void) { + static uint32_t start_ms = 0; + uint32_t curr_ms = board_millis(); + if (start_ms == curr_ms) return;// not enough time + start_ms = curr_ms; + for (size_t cnt = 0; cnt < sizeof(test_buffer_audio) / 2; cnt++) { + test_buffer_audio[cnt] = startVal++; + } + tud_audio_write((uint8_t *) test_buffer_audio, sizeof(test_buffer_audio)); } //--------------------------------------------------------------------+ @@ -152,8 +154,7 @@ void audio_task(void) //--------------------------------------------------------------------+ // Invoked when audio class specific set request received for an EP -bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; (void) pBuff; @@ -165,14 +166,15 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) ep; + (void) channelNum; + (void) ctrlSel; + (void) ep; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific set request received for an interface -bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; (void) pBuff; @@ -184,14 +186,15 @@ bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) itf; + (void) channelNum; + (void) ctrlSel; + (void) itf; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; // Page 91 in UAC2 specification @@ -206,40 +209,37 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); // If request is for our feature unit - if ( entityID == 2 ) - { - switch ( ctrlSel ) - { + if (entityID == 2) { + switch (ctrlSel) { case AUDIO_FU_CTRL_MUTE: // Request uses format layout 1 TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; + mute[channelNum] = ((audio_control_cur_1_t *) pBuff)->bCur; TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); - return true; + return true; case AUDIO_FU_CTRL_VOLUME: // Request uses format layout 2 TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); - volume[channelNum] = (uint16_t) ((audio_control_cur_2_t*) pBuff)->bCur; + volume[channelNum] = (uint16_t) ((audio_control_cur_2_t *) pBuff)->bCur; TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); - return true; + return true; // Unknown/Unsupported control default: TU_BREAKPOINT(); - return false; + return false; } } - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an EP -bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -247,16 +247,17 @@ bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) ep; + (void) channelNum; + (void) ctrlSel; + (void) ep; // return tud_control_xfer(rhport, p_request, &tmp, 1); - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an interface -bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -264,14 +265,15 @@ bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) itf; + (void) channelNum; + (void) ctrlSel; + (void) itf; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -281,12 +283,9 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * uint8_t entityID = TU_U16_HIGH(p_request->wIndex); // Input terminal (Microphone input) - if (entityID == 1) - { - switch ( ctrlSel ) - { - case AUDIO_TE_CTRL_CONNECTOR: - { + if (entityID == 1) { + switch (ctrlSel) { + case AUDIO_TE_CTRL_CONNECTOR: { // The terminal connector control only has a get request with only the CUR attribute. audio_desc_channel_cluster_t ret; @@ -297,9 +296,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * TU_LOG2(" Get terminal connector\r\n"); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); - } - break; + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); + } break; // Unknown/Unsupported control selector default: @@ -309,43 +307,40 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } // Feature unit - if (entityID == 2) - { - switch ( ctrlSel ) - { + if (entityID == 2) { + switch (ctrlSel) { case AUDIO_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away // There does not exist a range parameter block for mute TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute[channelNum], 1); case AUDIO_FU_CTRL_VOLUME: - switch ( p_request->bRequest ) - { + switch (p_request->bRequest) { case AUDIO_CS_REQ_CUR: TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); case AUDIO_CS_REQ_RANGE: TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); // Copy values - only for testing - better is version below audio_control_range_2_n_t(1) - ret; + ret; ret.wNumSubRanges = 1; - ret.subrange[0].bMin = -90; // -90 dB - ret.subrange[0].bMax = 90; // +90 dB - ret.subrange[0].bRes = 1; // 1 dB steps + ret.subrange[0].bMin = -90;// -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); // Unknown/Unsupported control default: TU_BREAKPOINT(); return false; } - break; + break; // Unknown/Unsupported control default: @@ -355,33 +350,30 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } // Clock Source unit - if ( entityID == 4 ) - { - switch ( ctrlSel ) - { + if (entityID == 4) { + switch (ctrlSel) { case AUDIO_CS_CTRL_SAM_FREQ: // channelNum is always zero in this case - switch ( p_request->bRequest ) - { + switch (p_request->bRequest) { case AUDIO_CS_REQ_CUR: TU_LOG2(" Get Sample Freq.\r\n"); - return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); case AUDIO_CS_REQ_RANGE: TU_LOG2(" Get Sample Freq. range\r\n"); - return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); - // Unknown/Unsupported control + // Unknown/Unsupported control default: TU_BREAKPOINT(); return false; } - break; + break; case AUDIO_CS_CTRL_CLK_VALID: // Only cur attribute exists for this request TU_LOG2(" Get Sample Freq. valid\r\n"); - return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); // Unknown/Unsupported control default: @@ -391,39 +383,10 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } TU_LOG2(" Unsupported entity: %d\r\n", entityID); - return false; // Yet not implemented + return false;// Yet not implemented } -bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void) rhport; - (void) itf; - (void) ep_in; - (void) cur_alt_setting; - - tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_EP_SZ_IN - 2); - - return true; -} - -bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void) rhport; - (void) n_bytes_copied; - (void) itf; - (void) ep_in; - (void) cur_alt_setting; - - for (size_t cnt = 0; cnt < (CFG_TUD_AUDIO_EP_SZ_IN - 2) / 2; cnt++) - { - test_buffer_audio[cnt] = startVal++; - } - - return true; -} - -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; (void) p_request; startVal = 0; @@ -434,15 +397,14 @@ bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) return;// not enough time start_ms += blink_interval_ms; board_led_write(led_state); - led_state = 1 - led_state; // toggle + led_state = 1 - led_state;// toggle } diff --git a/examples/device/audio_test/src/plot_audio_samples.py b/examples/device/audio_test/src/plot_audio_samples.py index ea6aa661e..2be8948ea 100755 --- a/examples/device/audio_test/src/plot_audio_samples.py +++ b/examples/device/audio_test/src/plot_audio_samples.py @@ -12,11 +12,11 @@ if __name__ == '__main__': # print(sd.query_devices()) fs = 48000 # Sample rate - duration = 100e-3 # Duration of recording + duration = 3 # Duration of recording if platform.system() == 'Windows': # MME is needed since there are more than one MicNode device APIs (at least in Windows) - device = 'Microphone (MicNode) MME' + device = 'Microphone (MicNode), Windows WASAPI' elif platform.system() == 'Darwin': device = 'MicNode' else: diff --git a/examples/device/audio_test/src/tusb_config.h b/examples/device/audio_test/src/tusb_config.h index 8c021e23c..b38958d7c 100644 --- a/examples/device/audio_test/src/tusb_config.h +++ b/examples/device/audio_test/src/tusb_config.h @@ -117,7 +117,7 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! #define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 8 : 1) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device #ifdef __cplusplus } diff --git a/examples/device/audio_test_freertos/src/main.c b/examples/device/audio_test_freertos/src/main.c index c5143c3fc..0a6cdfd4f 100644 --- a/examples/device/audio_test_freertos/src/main.c +++ b/examples/device/audio_test_freertos/src/main.c @@ -31,8 +31,8 @@ * $ python3 plot_audio_samples.py */ -#include #include +#include #include #include "bsp/board_api.h" @@ -42,25 +42,26 @@ // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" - #include "freertos/semphr.h" #include "freertos/queue.h" + #include "freertos/semphr.h" #include "freertos/task.h" #include "freertos/timers.h" - #define USBD_STACK_SIZE 4096 + #define USBD_STACK_SIZE 4096 #else #include "FreeRTOS.h" - #include "semphr.h" #include "queue.h" + #include "semphr.h" #include "task.h" #include "timers.h" // Increase stack size when debug log is enabled - #define USBD_STACK_SIZE (4*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1) + #define USBD_STACK_SIZE (4 * configMINIMAL_STACK_SIZE / 2) * (CFG_TUSB_DEBUG ? 2 : 1) #endif -#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE +#define AUDIO_STACK_SIZE configMINIMAL_STACK_SIZE //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES @@ -71,7 +72,7 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -82,34 +83,36 @@ enum { StackType_t blinky_stack[BLINKY_STACK_SIZE]; StaticTask_t blinky_taskdef; -StackType_t usb_device_stack[USBD_STACK_SIZE]; +StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; + +StackType_t audio_stack[AUDIO_STACK_SIZE]; +StaticTask_t audio_taskdef; #endif static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 -uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// +1 for master channel 0 uint32_t sampFreq; uint8_t clkValid; // Range states -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state -audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state +audio_control_range_4_n_t(1) sampleFreqRng; // Sample frequency range state // Audio test data -uint16_t test_buffer_audio[(CFG_TUD_AUDIO_EP_SZ_IN - 2) / 2]; +uint16_t test_buffer_audio[CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX / 2]; uint16_t startVal = 0; -void led_blinking_task(void* param); -void usb_device_task(void* param); -void audio_task(void); +void led_blinking_task(void *param); +void usb_device_task(void *param); +void audio_isr_task(void *param); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // Init values @@ -126,16 +129,21 @@ int main(void) xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); // Create a task for tinyusb device stack - xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); + xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, usb_device_stack, &usb_device_taskdef); + + // Audio receive (I2S) ISR simulation + // To simulate a ISR the priority is set to the highest + xTaskCreateStatic(audio_isr_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, audio_stack, &audio_taskdef); #else xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); + xTaskCreate(audio_isr_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); #endif - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 - #if !TUSB_MCU_VENDOR_ESPRESSIF - vTaskStartScheduler(); - #endif +// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 +#if !TUSB_MCU_VENDOR_ESPRESSIF + vTaskStartScheduler(); +#endif return 0; } @@ -148,17 +156,15 @@ void app_main(void) { // USB Device Driver task // This top level thread process all usb events and invoke callbacks -void usb_device_task(void* param) -{ +void usb_device_task(void *param) { (void) param; // init device stack on configured roothub port // This should be called after scheduler/kernel is started. // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API. tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); if (board_init_after_tusb) { @@ -166,8 +172,7 @@ void usb_device_task(void* param) } // RTOS forever loop - while (1) - { + while (1) { // tinyusb device task tud_task(); } @@ -204,10 +209,18 @@ void tud_resume_cb(void) { // AUDIO Task //--------------------------------------------------------------------+ -void audio_task(void) -{ - // Yet to be filled - e.g. put meas data into TX FIFOs etc. - // asm("nop"); +// This task simulates an audio receive ISR, one frame is received every 1ms. +// We assume that the audio data is read from an I2S buffer. +// In a real application, this would be replaced with actual I2S receive callback. +void audio_isr_task(void *param) { + (void) param; + while (1) { + vTaskDelay(1); + for (size_t cnt = 0; cnt < sizeof(test_buffer_audio) / 2; cnt++) { + test_buffer_audio[cnt] = startVal++; + } + tud_audio_write((uint8_t *) test_buffer_audio, sizeof(test_buffer_audio)); + } } //--------------------------------------------------------------------+ @@ -215,8 +228,7 @@ void audio_task(void) //--------------------------------------------------------------------+ // Invoked when audio class specific set request received for an EP -bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; (void) pBuff; @@ -228,14 +240,15 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) ep; + (void) channelNum; + (void) ctrlSel; + (void) ep; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific set request received for an interface -bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; (void) pBuff; @@ -247,14 +260,15 @@ bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) itf; + (void) channelNum; + (void) ctrlSel; + (void) itf; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; // Page 91 in UAC2 specification @@ -269,40 +283,36 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); // If request is for our feature unit - if ( entityID == 2 ) - { - switch ( ctrlSel ) - { + if (entityID == 2) { + switch (ctrlSel) { case AUDIO_FU_CTRL_MUTE: // Request uses format layout 1 TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; + mute[channelNum] = ((audio_control_cur_1_t *) pBuff)->bCur; - TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); - return true; + TU_LOG1(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); + return true; case AUDIO_FU_CTRL_VOLUME: // Request uses format layout 2 TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); - volume[channelNum] = (uint16_t) ((audio_control_cur_2_t*) pBuff)->bCur; - - TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); - return true; + volume[channelNum] = (uint16_t) ((audio_control_cur_2_t *) pBuff)->bCur; + TU_LOG1(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); + return true; // Unknown/Unsupported control default: TU_BREAKPOINT(); - return false; + return false; } } - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an EP -bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -310,14 +320,15 @@ bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) ep; + (void) channelNum; + (void) ctrlSel; + (void) ep; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an interface -bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -325,14 +336,15 @@ bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) itf; + (void) channelNum; + (void) ctrlSel; + (void) itf; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -342,12 +354,9 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * uint8_t entityID = TU_U16_HIGH(p_request->wIndex); // Input terminal (Microphone input) - if (entityID == 1) - { - switch ( ctrlSel ) - { - case AUDIO_TE_CTRL_CONNECTOR: - { + if (entityID == 1) { + switch (ctrlSel) { + case AUDIO_TE_CTRL_CONNECTOR: { // The terminal connector control only has a get request with only the CUR attribute. audio_desc_channel_cluster_t ret; @@ -356,11 +365,10 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * ret.bmChannelConfig = (audio_channel_config_t) 0; ret.iChannelNames = 0; - TU_LOG2(" Get terminal connector\r\n"); + TU_LOG1(" Get terminal connector\r\n"); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); - } - break; + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); + } break; // Unknown/Unsupported control selector default: @@ -370,43 +378,40 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } // Feature unit - if (entityID == 2) - { - switch ( ctrlSel ) - { + if (entityID == 2) { + switch (ctrlSel) { case AUDIO_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away // There does not exist a range parameter block for mute - TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); + TU_LOG1(" Get Mute of channel: %u\r\n", channelNum); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute[channelNum], 1); case AUDIO_FU_CTRL_VOLUME: - switch ( p_request->bRequest ) - { + switch (p_request->bRequest) { case AUDIO_CS_REQ_CUR: - TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); + TU_LOG1(" Get Volume of channel: %u\r\n", channelNum); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); case AUDIO_CS_REQ_RANGE: - TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); + TU_LOG1(" Get Volume range of channel: %u\r\n", channelNum); // Copy values - only for testing - better is version below audio_control_range_2_n_t(1) - ret; + ret; ret.wNumSubRanges = 1; - ret.subrange[0].bMin = -90; // -90 dB - ret.subrange[0].bMax = 90; // +90 dB - ret.subrange[0].bRes = 1; // 1 dB steps + ret.subrange[0].bMin = -90;// -90 dB + ret.subrange[0].bMax = 90; // +90 dB + ret.subrange[0].bRes = 1; // 1 dB steps - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); // Unknown/Unsupported control default: TU_BREAKPOINT(); return false; } - break; + break; // Unknown/Unsupported control default: @@ -416,33 +421,30 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } // Clock Source unit - if ( entityID == 4 ) - { - switch ( ctrlSel ) - { + if (entityID == 4) { + switch (ctrlSel) { case AUDIO_CS_CTRL_SAM_FREQ: // channelNum is always zero in this case - switch ( p_request->bRequest ) - { + switch (p_request->bRequest) { case AUDIO_CS_REQ_CUR: - TU_LOG2(" Get Sample Freq.\r\n"); - return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + TU_LOG1(" Get Sample Freq.\r\n"); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); case AUDIO_CS_REQ_RANGE: - TU_LOG2(" Get Sample Freq. range\r\n"); - return tud_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); + TU_LOG1(" Get Sample Freq. range\r\n"); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampleFreqRng, sizeof(sampleFreqRng)); - // Unknown/Unsupported control + // Unknown/Unsupported control default: TU_BREAKPOINT(); return false; } - break; + break; case AUDIO_CS_CTRL_CLK_VALID: // Only cur attribute exists for this request - TU_LOG2(" Get Sample Freq. valid\r\n"); - return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); + TU_LOG1(" Get Sample Freq. valid\r\n"); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); // Unknown/Unsupported control default: @@ -451,40 +453,11 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } } - TU_LOG2(" Unsupported entity: %d\r\n", entityID); - return false; // Yet not implemented + TU_LOG1(" Unsupported entity: %d\r\n", entityID); + return false;// Yet not implemented } -bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void) rhport; - (void) itf; - (void) ep_in; - (void) cur_alt_setting; - - tud_audio_write ((uint8_t *)test_buffer_audio, CFG_TUD_AUDIO_EP_SZ_IN - 2); - - return true; -} - -bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void) rhport; - (void) n_bytes_copied; - (void) itf; - (void) ep_in; - (void) cur_alt_setting; - - for (size_t cnt = 0; cnt < (CFG_TUD_AUDIO_EP_SZ_IN - 2) / 2; cnt++) - { - test_buffer_audio[cnt] = startVal++; - } - - return true; -} - -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; (void) p_request; startVal = 0; @@ -495,7 +468,7 @@ bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void* param) { +void led_blinking_task(void *param) { (void) param; static uint32_t start_ms = 0; static bool led_state = false; @@ -506,6 +479,6 @@ void led_blinking_task(void* param) { start_ms += blink_interval_ms; board_led_write(led_state); - led_state = 1 - led_state; // toggle + led_state = 1 - led_state;// toggle } } diff --git a/examples/device/audio_test_freertos/src/plot_audio_samples.py b/examples/device/audio_test_freertos/src/plot_audio_samples.py index 46738eb3f..b6d8e824b 100755 --- a/examples/device/audio_test_freertos/src/plot_audio_samples.py +++ b/examples/device/audio_test_freertos/src/plot_audio_samples.py @@ -11,11 +11,11 @@ if __name__ == '__main__': # print(sd.query_devices()) fs = 48000 # Sample rate - duration = 1000e-3 # Duration of recording + duration = 3 # Duration of recording if platform.system() == 'Windows': # MME is needed since there are more than one MicNode device APIs (at least in Windows) - device = 'Microphone (MicNode) MME' + device = 'Microphone (MicNode), Windows WASAPI' elif platform.system() == 'Darwin': device = 'MicNode' else: diff --git a/examples/device/audio_test_freertos/src/tusb_config.h b/examples/device/audio_test_freertos/src/tusb_config.h index 61c5cbb96..4b61e72bc 100644 --- a/examples/device/audio_test_freertos/src/tusb_config.h +++ b/examples/device/audio_test_freertos/src/tusb_config.h @@ -123,7 +123,7 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX 1 // Driver gets this info from the descriptors - we define it here to use it to setup the descriptors and to do calculations with it below - be aware: for different number of channels you need another descriptor! #define CFG_TUD_AUDIO_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX CFG_TUD_AUDIO_EP_SZ_IN -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 8 : 1) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_EP_SZ_IN // Example write FIFO every 1ms, so it should be 8 times larger for HS device #ifdef __cplusplus } diff --git a/examples/device/audio_test_multi_rate/src/main.c b/examples/device/audio_test_multi_rate/src/main.c index 8fa902a04..704a75b09 100644 --- a/examples/device/audio_test_multi_rate/src/main.c +++ b/examples/device/audio_test_multi_rate/src/main.c @@ -32,8 +32,8 @@ * $ python3 plot_audio_samples.py */ -#include #include +#include #include #include "bsp/board_api.h" @@ -49,7 +49,7 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, @@ -59,8 +59,8 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 -uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +bool mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1]; // +1 for master channel 0 +uint16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// +1 for master channel 0 uint32_t sampFreq; uint8_t bytesPerSample; uint8_t clkValid; @@ -68,39 +68,36 @@ uint8_t clkValid; // Range states // List of supported sample rates static const uint32_t sampleRatesList[] = -{ - 32000, 48000, 96000 -}; + { + 32000, 48000, 96000}; -#define N_sampleRates TU_ARRAY_SIZE(sampleRatesList) +#define N_sampleRates TU_ARRAY_SIZE(sampleRatesList) // Bytes per format of every Alt settings static const uint8_t bytesPerSampleAltList[CFG_TUD_AUDIO_FUNC_1_N_FORMATS] = -{ - CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, - CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, + { + CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, + CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, }; -audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX+1]; // Volume range state +audio_control_range_2_n_t(1) volumeRng[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX + 1];// Volume range state // Audio test data -CFG_TUD_MEM_ALIGN uint8_t test_buffer_audio[CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; +CFG_TUD_MEM_ALIGN uint8_t test_buffer_audio[(TUD_OPT_HIGH_SPEED ? 8 : 1) * CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX]; uint16_t startVal = 0; void led_blinking_task(void); void audio_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); if (board_init_after_tusb) { @@ -111,9 +108,8 @@ int main(void) sampFreq = sampleRatesList[0]; clkValid = 1; - while (1) - { - tud_task(); // tinyusb device task + while (1) { + tud_task();// tinyusb device task led_blinking_task(); audio_task(); } @@ -127,29 +123,25 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ +void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } @@ -157,10 +149,29 @@ void tud_resume_cb(void) // AUDIO Task //--------------------------------------------------------------------+ -void audio_task(void) -{ - // Yet to be filled - e.g. put meas data into TX FIFOs etc. - // asm("nop"); +// This task simulates an audio receive callback, one frame is received every 1ms. +// We assume that the audio data is read from an I2S buffer. +// In a real application, this would be replaced with actual I2S receive callback. +void audio_task(void) { + static uint32_t start_ms = 0; + uint32_t curr_ms = board_millis(); + if (start_ms == curr_ms) return;// not enough time + start_ms = curr_ms; + // 16bit + if (bytesPerSample == 2) { + uint16_t *pData_16 = (uint16_t *) ((void *) test_buffer_audio); + for (size_t cnt = 0; cnt < sampFreq / 1000; cnt++) { + pData_16[cnt] = startVal++; + } + } + // 24bit in 32bit slot + else if (bytesPerSample == 4) { + uint32_t *pData_32 = (uint32_t *) ((void *) test_buffer_audio); + for (size_t cnt = 0; cnt < sampFreq / 1000; cnt++) { + pData_32[cnt] = (uint32_t) startVal++ << 16U; + } + } + tud_audio_write((uint8_t *) test_buffer_audio, (uint16_t) (sampFreq / 1000 * bytesPerSample)); } //--------------------------------------------------------------------+ @@ -168,23 +179,20 @@ void audio_task(void) //--------------------------------------------------------------------+ // Invoked when set interface is called, typically on start/stop streaming or format change -bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void)rhport; +bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; //uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); // Clear buffer when streaming format is changed - if(alt != 0) - { - bytesPerSample = bytesPerSampleAltList[alt-1]; + if (alt != 0) { + bytesPerSample = bytesPerSampleAltList[alt - 1]; } return true; } // Invoked when audio class specific set request received for an EP -bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; (void) pBuff; @@ -196,14 +204,15 @@ bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) ep; + (void) channelNum; + (void) ctrlSel; + (void) ep; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific set request received for an interface -bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; (void) pBuff; @@ -215,14 +224,15 @@ bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) itf; + (void) channelNum; + (void) ctrlSel; + (void) itf; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff) -{ +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *pBuff) { (void) rhport; // Page 91 in UAC2 specification @@ -237,49 +247,45 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * TU_VERIFY(p_request->bRequest == AUDIO_CS_REQ_CUR); // If request is for our feature unit - if ( entityID == UAC2_ENTITY_FEATURE_UNIT ) - { - switch ( ctrlSel ) - { + if (entityID == UAC2_ENTITY_FEATURE_UNIT) { + switch (ctrlSel) { case AUDIO_FU_CTRL_MUTE: // Request uses format layout 1 TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_1_t)); - mute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; + mute[channelNum] = ((audio_control_cur_1_t *) pBuff)->bCur; TU_LOG2(" Set Mute: %d of channel: %u\r\n", mute[channelNum], channelNum); - return true; + return true; case AUDIO_FU_CTRL_VOLUME: // Request uses format layout 2 TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_2_t)); - volume[channelNum] = (uint16_t) ((audio_control_cur_2_t*) pBuff)->bCur; + volume[channelNum] = (uint16_t) ((audio_control_cur_2_t *) pBuff)->bCur; TU_LOG2(" Set Volume: %d dB of channel: %u\r\n", volume[channelNum], channelNum); - return true; + return true; // Unknown/Unsupported control default: TU_BREAKPOINT(); - return false; + return false; } } // Clock Source unit - if ( entityID == UAC2_ENTITY_CLOCK ) - { - switch ( ctrlSel ) - { + if (entityID == UAC2_ENTITY_CLOCK) { + switch (ctrlSel) { case AUDIO_CS_CTRL_SAM_FREQ: TU_VERIFY(p_request->wLength == sizeof(audio_control_cur_4_t)); - sampFreq = (uint32_t)((audio_control_cur_4_t *)pBuff)->bCur; + sampFreq = (uint32_t) ((audio_control_cur_4_t *) pBuff)->bCur; TU_LOG2("Clock set current freq: %" PRIu32 "\r\n", sampFreq); return true; - break; + break; // Unknown/Unsupported control default: @@ -288,12 +294,11 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } } - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an EP -bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -301,16 +306,17 @@ bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_re uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t ep = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) ep; + (void) channelNum; + (void) ctrlSel; + (void) ep; // return tud_control_xfer(rhport, p_request, &tmp, 1); - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an interface -bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -318,14 +324,15 @@ bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_r uint8_t ctrlSel = TU_U16_HIGH(p_request->wValue); uint8_t itf = TU_U16_LOW(p_request->wIndex); - (void) channelNum; (void) ctrlSel; (void) itf; + (void) channelNum; + (void) ctrlSel; + (void) itf; - return false; // Yet not implemented + return false;// Yet not implemented } // Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; // Page 91 in UAC2 specification @@ -335,12 +342,9 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * uint8_t entityID = TU_U16_HIGH(p_request->wIndex); // Input terminal (Microphone input) - if (entityID == UAC2_ENTITY_INPUT_TERMINAL) - { - switch ( ctrlSel ) - { - case AUDIO_TE_CTRL_CONNECTOR: - { + if (entityID == UAC2_ENTITY_INPUT_TERMINAL) { + switch (ctrlSel) { + case AUDIO_TE_CTRL_CONNECTOR: { // The terminal connector control only has a get request with only the CUR attribute. audio_desc_channel_cluster_t ret; @@ -351,9 +355,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * TU_LOG2(" Get terminal connector\r\n"); - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); - } - break; + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); + } break; // Unknown/Unsupported control selector default: @@ -363,43 +366,40 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } // Feature unit - if (entityID == UAC2_ENTITY_FEATURE_UNIT) - { - switch ( ctrlSel ) - { + if (entityID == UAC2_ENTITY_FEATURE_UNIT) { + switch (ctrlSel) { case AUDIO_FU_CTRL_MUTE: // Audio control mute cur parameter block consists of only one byte - we thus can send it right away // There does not exist a range parameter block for mute TU_LOG2(" Get Mute of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &mute[channelNum], 1); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &mute[channelNum], 1); case AUDIO_FU_CTRL_VOLUME: - switch ( p_request->bRequest ) - { + switch (p_request->bRequest) { case AUDIO_CS_REQ_CUR: TU_LOG2(" Get Volume of channel: %u\r\n", channelNum); - return tud_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &volume[channelNum], sizeof(volume[channelNum])); case AUDIO_CS_REQ_RANGE: TU_LOG2(" Get Volume range of channel: %u\r\n", channelNum); // Copy values - only for testing - better is version below audio_control_range_2_n_t(1) - ret; + ret; ret.wNumSubRanges = 1; - ret.subrange[0].bMin = -90; // -90 dB - ret.subrange[0].bMax = 30; // +30 dB - ret.subrange[0].bRes = 1; // 1 dB steps + ret.subrange[0].bMin = -90;// -90 dB + ret.subrange[0].bMax = 30; // +30 dB + ret.subrange[0].bRes = 1; // 1 dB steps - return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void*) &ret, sizeof(ret)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, (void *) &ret, sizeof(ret)); // Unknown/Unsupported control default: TU_BREAKPOINT(); return false; } - break; + break; // Unknown/Unsupported control default: @@ -409,46 +409,40 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } // Clock Source unit - if ( entityID == UAC2_ENTITY_CLOCK ) - { - switch ( ctrlSel ) - { + if (entityID == UAC2_ENTITY_CLOCK) { + switch (ctrlSel) { case AUDIO_CS_CTRL_SAM_FREQ: // channelNum is always zero in this case - switch ( p_request->bRequest ) - { + switch (p_request->bRequest) { case AUDIO_CS_REQ_CUR: TU_LOG2(" Get Sample Freq.\r\n"); - return tud_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &sampFreq, sizeof(sampFreq)); - case AUDIO_CS_REQ_RANGE: - { + case AUDIO_CS_REQ_RANGE: { TU_LOG2(" Get Sample Freq. range\r\n"); audio_control_range_4_n_t(N_sampleRates) rangef = - { - .wNumSubRanges = tu_htole16(N_sampleRates) - }; + { + .wNumSubRanges = tu_htole16(N_sampleRates)}; TU_LOG1("Clock get %d freq ranges\r\n", N_sampleRates); - for(uint8_t i = 0; i < N_sampleRates; i++) - { - rangef.subrange[i].bMin = (int32_t)sampleRatesList[i]; - rangef.subrange[i].bMax = (int32_t)sampleRatesList[i]; - rangef.subrange[i].bRes = 0; - TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int)rangef.subrange[i].bMin, (int)rangef.subrange[i].bMax, (int)rangef.subrange[i].bRes); + for (uint8_t i = 0; i < N_sampleRates; i++) { + rangef.subrange[i].bMin = (int32_t) sampleRatesList[i]; + rangef.subrange[i].bMax = (int32_t) sampleRatesList[i]; + rangef.subrange[i].bRes = 0; + TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int) rangef.subrange[i].bMin, (int) rangef.subrange[i].bMax, (int) rangef.subrange[i].bRes); } return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &rangef, sizeof(rangef)); } - // Unknown/Unsupported control + // Unknown/Unsupported control default: TU_BREAKPOINT(); return false; } - break; + break; case AUDIO_CS_CTRL_CLK_VALID: // Only cur attribute exists for this request TU_LOG2(" Get Sample Freq. valid\r\n"); - return tud_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, p_request, &clkValid, sizeof(clkValid)); // Unknown/Unsupported control default: @@ -458,53 +452,10 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * } TU_LOG2(" Unsupported entity: %d\r\n", entityID); - return false; // Yet not implemented + return false;// Yet not implemented } -bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void) rhport; - (void) itf; - (void) ep_in; - (void) cur_alt_setting; - - tud_audio_write((uint8_t *)test_buffer_audio, (uint16_t)(sampFreq / (TUD_OPT_HIGH_SPEED ? 8000 : 1000) * bytesPerSample)); - - return true; -} - -bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void) rhport; - (void) n_bytes_copied; - (void) itf; - (void) ep_in; - (void) cur_alt_setting; - - // 16bit - if(bytesPerSample == 2) - { - uint16_t* pData_16 = (uint16_t*)((void*)test_buffer_audio); - for (size_t cnt = 0; cnt < sampFreq / (TUD_OPT_HIGH_SPEED ? 8000 : 1000); cnt++) - { - pData_16[cnt] = startVal++; - } - } - // 24bit in 32bit slot - else if(bytesPerSample == 4) - { - uint32_t* pData_32 = (uint32_t*)((void*)test_buffer_audio); - for (size_t cnt = 0; cnt < sampFreq / (TUD_OPT_HIGH_SPEED ? 8000 : 1000); cnt++) - { - pData_32[cnt] = (uint32_t)startVal++ << 16U; - } - } - - return true; -} - -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; (void) p_request; startVal = 0; @@ -515,15 +466,14 @@ bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) return;// not enough time start_ms += blink_interval_ms; board_led_write(led_state); - led_state = 1 - led_state; // toggle + led_state = 1 - led_state;// toggle } diff --git a/examples/device/audio_test_multi_rate/src/tusb_config.h b/examples/device/audio_test_multi_rate/src/tusb_config.h index 1c8288bce..d9b925dcf 100644 --- a/examples/device/audio_test_multi_rate/src/tusb_config.h +++ b/examples/device/audio_test_multi_rate/src/tusb_config.h @@ -133,7 +133,8 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN) // Maximum EP IN size for all AS alternate settings used -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX // Example write FIFO every 1ms, so it should be 8 times larger for HS device + #ifdef __cplusplus } #endif diff --git a/examples/device/cdc_uac2/skip.txt b/examples/device/cdc_uac2/skip.txt new file mode 100644 index 000000000..a2a76af0e --- /dev/null +++ b/examples/device/cdc_uac2/skip.txt @@ -0,0 +1,8 @@ +mcu:LPC11UXX +mcu:LPC13XX +mcu:NUC121 +mcu:SAMD11 +mcu:SAME5X +mcu:SAMG +board:stm32l052dap52 +family:espressif diff --git a/examples/device/cdc_uac2/src/main.c b/examples/device/cdc_uac2/src/main.c index b148593da..bc87f6e3c 100644 --- a/examples/device/cdc_uac2/src/main.c +++ b/examples/device/cdc_uac2/src/main.c @@ -39,6 +39,7 @@ extern uint32_t blink_interval_ms; #endif void led_blinking_task(void); +void audio_task(void); /*------------- MAIN -------------*/ int main(void) @@ -62,7 +63,7 @@ int main(void) { tud_task(); // TinyUSB device task led_blinking_task(); - + audio_task(); #if (CFG_TUSB_MCU == OPT_MCU_RP2040) // printf("Hello, world!\r\n"); #endif diff --git a/examples/device/cdc_uac2/src/tusb_config.h b/examples/device/cdc_uac2/src/tusb_config.h index 93489cf62..2318ccf73 100644 --- a/examples/device/cdc_uac2/src/tusb_config.h +++ b/examples/device/cdc_uac2/src/tusb_config.h @@ -145,8 +145,8 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN) #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN) // Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX // Example read FIFO every 1ms, so it should be 8 times larger for HS device // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 @@ -154,8 +154,8 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT) #define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX // Example read FIFO every 1ms, so it should be 8 times larger for HS device // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) #define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 2 @@ -164,8 +164,11 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64 // CDC FIFO size of TX and RX -#define CFG_TUD_CDC_RX_BUFSIZE 64 -#define CFG_TUD_CDC_TX_BUFSIZE 64 +#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) + +// CDC Endpoint transfer buffer size, more is faster +#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #ifdef __cplusplus } diff --git a/examples/device/cdc_uac2/src/uac2_app.c b/examples/device/cdc_uac2/src/uac2_app.c index 70b0949a9..7d5da5ed0 100644 --- a/examples/device/cdc_uac2/src/uac2_app.c +++ b/examples/device/cdc_uac2/src/uac2_app.c @@ -49,17 +49,36 @@ uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 -// Buffer for microphone data -int32_t mic_buf[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ / 4]; // Buffer for speaker data int32_t spk_buf[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ / 4]; // Speaker data size received in the last frame -int spk_data_size; +uint16_t spk_data_size; // Resolution per format const uint8_t resolutions_per_format[CFG_TUD_AUDIO_FUNC_1_N_FORMATS] = {CFG_TUD_AUDIO_FUNC_1_FORMAT_1_RESOLUTION_RX}; // Current resolution, update on format change uint8_t current_resolution; +//--------------------------------------------------------------------+ +// AUDIO Task +//--------------------------------------------------------------------+ + +// This task simulates an audio transfer callback, one frame is sent/received every 1ms. +// In a real application, this would be replaced with actual I2S send/receive callback. +void audio_task(void) { + static uint32_t start_ms = 0; + uint32_t curr_ms = board_millis(); + if (start_ms == curr_ms) return;// not enough time + start_ms = curr_ms; + // When new data arrived, copy data from speaker buffer, to microphone buffer + // and send it over + // Only support speaker & headphone both have the same resolution + // If one is 16bit another is 24bit be care of LOUD noise ! + spk_data_size = tud_audio_read(spk_buf, sizeof(spk_buf)); + if (spk_data_size) { + tud_audio_write((uint8_t *) spk_buf, spk_data_size); + } +} + // Helper for clock get requests static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request) { @@ -265,8 +284,6 @@ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_reque blink_interval_ms = BLINK_STREAMING; } - // Clear buffer when streaming format is changed - spk_data_size = 0; if(alt != 0) { current_resolution = resolutions_per_format[alt-1]; @@ -275,30 +292,6 @@ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_reque return true; } -bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting) -{ - (void)rhport; - (void)func_id; - (void)ep_out; - (void)cur_alt_setting; - - spk_data_size = tud_audio_read(spk_buf, n_bytes_received); - tud_audio_write(spk_buf, n_bytes_received); - - return true; -} - -bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void)rhport; - (void)itf; - (void)ep_in; - (void)cur_alt_setting; - - // This callback could be used to fill microphone data separately - return true; -} - //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ diff --git a/examples/device/cdc_uac2/src/usb_descriptors.c b/examples/device/cdc_uac2/src/usb_descriptors.c index 9f7255d8a..22d3cf05a 100644 --- a/examples/device/cdc_uac2/src/usb_descriptors.c +++ b/examples/device/cdc_uac2/src/usb_descriptors.c @@ -116,7 +116,7 @@ uint8_t const * tud_descriptor_device_cb(void) #define EPNUM_CDC_IN 0x84 #endif -uint8_t const desc_configuration[] = +uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), @@ -128,13 +128,78 @@ uint8_t const desc_configuration[] = TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 6, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64) }; +#if TUD_OPT_HIGH_SPEED +// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration + +// high speed configuration +uint8_t const desc_hs_configuration[] = { + // Config number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR(2, EPNUM_AUDIO_OUT, EPNUM_AUDIO_IN | 0x80), + + // CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 6, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512) +}; + +// other speed configuration +uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; + +// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed +tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, + .bcdUSB = 0x0100, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. +// device_qualifier descriptor describes information about a high-speed capable device that would +// change if the device were operating at the other speed. If not highspeed capable stall this request. +uint8_t const *tud_descriptor_device_qualifier_cb(void) { + return (uint8_t const *) &desc_device_qualifier; +} + +// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request +// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete +// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa +uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index; // for multiple configurations + + // if link speed is high return fullspeed config, and vice versa + // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG + memcpy(desc_other_speed_config, + (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration, + CONFIG_TOTAL_LEN); + + desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; + + return desc_other_speed_config; +} + +#endif // highspeed + // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void)index; // for multiple configurations - return desc_configuration; +#if TUD_OPT_HIGH_SPEED + // Although we are highspeed, host may be fullspeed. + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif } //--------------------------------------------------------------------+ diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 6b2ab0973..33b8ea0ef 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -37,9 +37,9 @@ // List of supported sample rates const uint32_t sample_rates[] = {44100, 48000}; -uint32_t current_sample_rate = 44100; +uint32_t current_sample_rate = 44100; -#define N_SAMPLE_RATES TU_ARRAY_SIZE(sample_rates) +#define N_SAMPLE_RATES TU_ARRAY_SIZE(sample_rates) /* Blink pattern * - 25 ms : streaming data @@ -47,16 +47,14 @@ uint32_t current_sample_rate = 44100; * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum -{ +enum { BLINK_STREAMING = 25, BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, }; -enum -{ +enum { VOLUME_CTRL_0_DB = 0, VOLUME_CTRL_10_DB = 2560, VOLUME_CTRL_20_DB = 5120, @@ -75,8 +73,8 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 -int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 +int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 +int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1];// +1 for master channel 0 // Buffer for microphone data int32_t mic_buf[CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ / 4]; @@ -95,15 +93,13 @@ void audio_task(void); void audio_control_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); if (board_init_after_tusb) { @@ -112,9 +108,8 @@ int main(void) TU_LOG1("Headset running\r\n"); - while (1) - { - tud_task(); // TinyUSB device task + while (1) { + tud_task();// TinyUSB device task audio_task(); audio_control_task(); led_blinking_task(); @@ -126,70 +121,57 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ - (void)remote_wakeup_en; +void tud_suspend_cb(bool remote_wakeup_en) { + (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } // Helper for clock get requests -static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request) -{ +static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); - if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) - { - if (request->bRequest == AUDIO_CS_REQ_CUR) - { + if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) { + if (request->bRequest == AUDIO_CS_REQ_CUR) { TU_LOG1("Clock get current freq %" PRIu32 "\r\n", current_sample_rate); - audio_control_cur_4_t curf = { (int32_t) tu_htole32(current_sample_rate) }; - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf)); - } - else if (request->bRequest == AUDIO_CS_REQ_RANGE) - { + audio_control_cur_4_t curf = {(int32_t) tu_htole32(current_sample_rate)}; + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &curf, sizeof(curf)); + } else if (request->bRequest == AUDIO_CS_REQ_RANGE) { audio_control_range_4_n_t(N_SAMPLE_RATES) rangef = - { - .wNumSubRanges = tu_htole16(N_SAMPLE_RATES) - }; + { + .wNumSubRanges = tu_htole16(N_SAMPLE_RATES)}; TU_LOG1("Clock get %d freq ranges\r\n", N_SAMPLE_RATES); - for(uint8_t i = 0; i < N_SAMPLE_RATES; i++) - { + for (uint8_t i = 0; i < N_SAMPLE_RATES; i++) { rangef.subrange[i].bMin = (int32_t) sample_rates[i]; rangef.subrange[i].bMax = (int32_t) sample_rates[i]; rangef.subrange[i].bRes = 0; - TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int)rangef.subrange[i].bMin, (int)rangef.subrange[i].bMax, (int)rangef.subrange[i].bRes); + TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int) rangef.subrange[i].bMin, (int) rangef.subrange[i].bMax, (int) rangef.subrange[i].bRes); } - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &rangef, sizeof(rangef)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &rangef, sizeof(rangef)); } - } - else if (request->bControlSelector == AUDIO_CS_CTRL_CLK_VALID && - request->bRequest == AUDIO_CS_REQ_CUR) - { - audio_control_cur_1_t cur_valid = { .bCur = 1 }; + } else if (request->bControlSelector == AUDIO_CS_CTRL_CLK_VALID && + request->bRequest == AUDIO_CS_REQ_CUR) { + audio_control_cur_1_t cur_valid = {.bCur = 1}; TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur); - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_valid, sizeof(cur_valid)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &cur_valid, sizeof(cur_valid)); } TU_LOG1("Clock get request not supported, entity = %u, selector = %u, request = %u\r\n", request->bEntityID, request->bControlSelector, request->bRequest); @@ -197,25 +179,21 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t } // Helper for clock set requests -static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) -{ - (void)rhport; +static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) { + (void) rhport; TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); - if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) - { + if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) { TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t)); - current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *)buf)->bCur; + current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *) buf)->bCur; TU_LOG1("Clock set current freq: %" PRIu32 "\r\n", current_sample_rate); return true; - } - else - { + } else { TU_LOG1("Clock set request not supported, entity = %u, selector = %u, request = %u\r\n", request->bEntityID, request->bControlSelector, request->bRequest); return false; @@ -223,33 +201,25 @@ static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t } // Helper for feature unit get requests -static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request) -{ +static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT); - if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR) - { - audio_control_cur_1_t mute1 = { .bCur = mute[request->bChannelNumber] }; + if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR) { + audio_control_cur_1_t mute1 = {.bCur = mute[request->bChannelNumber]}; TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur); - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &mute1, sizeof(mute1)); - } - else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) - { - if (request->bRequest == AUDIO_CS_REQ_RANGE) - { + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &mute1, sizeof(mute1)); + } else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) { + if (request->bRequest == AUDIO_CS_REQ_RANGE) { audio_control_range_2_n_t(1) range_vol = { - .wNumSubRanges = tu_htole16(1), - .subrange[0] = { .bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256) } - }; + .wNumSubRanges = tu_htole16(1), + .subrange[0] = {.bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256)}}; TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber, range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256); - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &range_vol, sizeof(range_vol)); - } - else if (request->bRequest == AUDIO_CS_REQ_CUR) - { - audio_control_cur_2_t cur_vol = { .bCur = tu_htole16(volume[request->bChannelNumber]) }; + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &range_vol, sizeof(range_vol)); + } else if (request->bRequest == AUDIO_CS_REQ_CUR) { + audio_control_cur_2_t cur_vol = {.bCur = tu_htole16(volume[request->bChannelNumber])}; TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256); - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_vol, sizeof(cur_vol)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &cur_vol, sizeof(cur_vol)); } } TU_LOG1("Feature unit get request not supported, entity = %u, selector = %u, request = %u\r\n", @@ -259,35 +229,29 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req } // Helper for feature unit set requests -static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) -{ - (void)rhport; +static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) { + (void) rhport; TU_ASSERT(request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT); TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); - if (request->bControlSelector == AUDIO_FU_CTRL_MUTE) - { + if (request->bControlSelector == AUDIO_FU_CTRL_MUTE) { TU_VERIFY(request->wLength == sizeof(audio_control_cur_1_t)); - mute[request->bChannelNumber] = ((audio_control_cur_1_t const *)buf)->bCur; + mute[request->bChannelNumber] = ((audio_control_cur_1_t const *) buf)->bCur; TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); return true; - } - else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) - { + } else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) { TU_VERIFY(request->wLength == sizeof(audio_control_cur_2_t)); - volume[request->bChannelNumber] = ((audio_control_cur_2_t const *)buf)->bCur; + volume[request->bChannelNumber] = ((audio_control_cur_2_t const *) buf)->bCur; TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256); return true; - } - else - { + } else { TU_LOG1("Feature unit set request not supported, entity = %u, selector = %u, request = %u\r\n", request->bEntityID, request->bControlSelector, request->bRequest); return false; @@ -299,16 +263,14 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req //--------------------------------------------------------------------+ // Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) -{ - audio_control_request_t const *request = (audio_control_request_t const *)p_request; +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + audio_control_request_t const *request = (audio_control_request_t const *) p_request; if (request->bEntityID == UAC2_ENTITY_CLOCK) return tud_audio_clock_get_request(rhport, request); if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) return tud_audio_feature_unit_get_request(rhport, request); - else - { + else { TU_LOG1("Get request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); } @@ -316,9 +278,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p } // Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) -{ - audio_control_request_t const *request = (audio_control_request_t const *)p_request; +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) { + audio_control_request_t const *request = (audio_control_request_t const *) p_request; if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) return tud_audio_feature_unit_set_request(rhport, request, buf); @@ -330,108 +291,82 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p return false; } -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void)rhport; +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt == 0) - blink_interval_ms = BLINK_MOUNTED; + blink_interval_ms = BLINK_MOUNTED; return true; } -bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void)rhport; +bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); TU_LOG2("Set interface %d alt %d\r\n", itf, alt); if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt != 0) - blink_interval_ms = BLINK_STREAMING; + blink_interval_ms = BLINK_STREAMING; // Clear buffer when streaming format is changed spk_data_size = 0; - if(alt != 0) - { - current_resolution = resolutions_per_format[alt-1]; + if (alt != 0) { + current_resolution = resolutions_per_format[alt - 1]; } return true; } -bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting) -{ - (void)rhport; - (void)func_id; - (void)ep_out; - (void)cur_alt_setting; - - spk_data_size = tud_audio_read(spk_buf, n_bytes_received); - return true; -} - -bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, uint8_t cur_alt_setting) -{ - (void)rhport; - (void)itf; - (void)ep_in; - (void)cur_alt_setting; - - // This callback could be used to fill microphone data separately - return true; -} - //--------------------------------------------------------------------+ // AUDIO Task //--------------------------------------------------------------------+ -void audio_task(void) -{ +// This task simulates an audio transfer callback, one frame is sent/received every 1ms. +// In a real application, this would be replaced with actual I2S send/receive callback. +void audio_task(void) { + static uint32_t start_ms = 0; + uint32_t curr_ms = board_millis(); + if (start_ms == curr_ms) return;// not enough time + start_ms = curr_ms; // When new data arrived, copy data from speaker buffer, to microphone buffer // and send it over // Only support speaker & headphone both have the same resolution // If one is 16bit another is 24bit be care of LOUD noise ! - if (spk_data_size) - { - if (current_resolution == 16) - { - int16_t *src = (int16_t*)spk_buf; - int16_t *limit = (int16_t*)spk_buf + spk_data_size / 2; - int16_t *dst = (int16_t*)mic_buf; - while (src < limit) - { + spk_data_size = tud_audio_read(spk_buf, sizeof(spk_buf)); + if (spk_data_size) { + if (current_resolution == 16) { + int16_t *src = (int16_t *) spk_buf; + int16_t *limit = (int16_t *) spk_buf + spk_data_size / 2; + int16_t *dst = (int16_t *) mic_buf; + while (src < limit) { // Combine two channels into one int32_t left = *src++; int32_t right = *src++; *dst++ = (int16_t) ((left >> 1) + (right >> 1)); } - tud_audio_write((uint8_t *)mic_buf, (uint16_t) (spk_data_size / 2)); + tud_audio_write((uint8_t *) mic_buf, (uint16_t) (spk_data_size / 2)); spk_data_size = 0; - } - else if (current_resolution == 24) - { + } else if (current_resolution == 24) { int32_t *src = spk_buf; int32_t *limit = spk_buf + spk_data_size / 4; int32_t *dst = mic_buf; - while (src < limit) - { + while (src < limit) { // Combine two channels into one int32_t left = *src++; int32_t right = *src++; *dst++ = (int32_t) ((uint32_t) ((left >> 1) + (right >> 1)) & 0xffffff00ul); } - tud_audio_write((uint8_t *)mic_buf, (uint16_t) (spk_data_size / 2)); + tud_audio_write((uint8_t *) mic_buf, (uint16_t) (spk_data_size / 2)); spk_data_size = 0; } } } -void audio_control_task(void) -{ +void audio_control_task(void) { // Press on-board button to control volume // Open host volume control, volume should switch between 10% and 100% @@ -440,27 +375,25 @@ void audio_control_task(void) static uint32_t start_ms = 0; static uint32_t btn_prev = 0; - if ( board_millis() - start_ms < interval_ms) return; // not enough time + if (board_millis() - start_ms < interval_ms) return;// not enough time start_ms += interval_ms; uint32_t btn = board_button_read(); - if (!btn_prev && btn) - { + if (!btn_prev && btn) { // Adjust volume between 0dB (100%) and -30dB (10%) - for (int i = 0; i < CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1; i++) - { + for (int i = 0; i < CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1; i++) { volume[i] = volume[i] == 0 ? -VOLUME_CTRL_30_DB : 0; } // 6.1 Interrupt Data Message const audio_interrupt_data_t data = { - .bInfo = 0, // Class-specific interrupt, originated from an interface - .bAttribute = AUDIO_CS_REQ_CUR, // Caused by current settings - .wValue_cn_or_mcn = 0, // CH0: master volume - .wValue_cs = AUDIO_FU_CTRL_VOLUME, // Volume change - .wIndex_ep_or_int = 0, // From the interface itself - .wIndex_entity_id = UAC2_ENTITY_SPK_FEATURE_UNIT, // From feature unit + .bInfo = 0, // Class-specific interrupt, originated from an interface + .bAttribute = AUDIO_CS_REQ_CUR, // Caused by current settings + .wValue_cn_or_mcn = 0, // CH0: master volume + .wValue_cs = AUDIO_FU_CTRL_VOLUME, // Volume change + .wIndex_ep_or_int = 0, // From the interface itself + .wIndex_entity_id = UAC2_ENTITY_SPK_FEATURE_UNIT,// From feature unit }; tud_audio_int_write(&data); @@ -472,8 +405,7 @@ void audio_control_task(void) //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; diff --git a/examples/device/uac2_headset/src/tusb_config.h b/examples/device/uac2_headset/src/tusb_config.h index c921a37ae..e738a09af 100644 --- a/examples/device/uac2_headset/src/tusb_config.h +++ b/examples/device/uac2_headset/src/tusb_config.h @@ -146,8 +146,8 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_TX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX) -#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN)*4 #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_IN, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_IN) // Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX // Example read FIFO every 1ms, so it should be 8 times larger for HS device // EP and buffer size - for isochronous EP´s, the buffer and EP size are equal (different sizes would not make sense) #define CFG_TUD_AUDIO_ENABLE_EP_OUT 1 @@ -155,8 +155,8 @@ extern "C" { #define CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_1_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) #define CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT TUD_AUDIO_EP_SIZE(CFG_TUD_AUDIO_FUNC_1_MAX_SAMPLE_RATE, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_N_BYTES_PER_SAMPLE_RX, CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX) -#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT)*2 #define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX TU_MAX(CFG_TUD_AUDIO_FUNC_1_FORMAT_1_EP_SZ_OUT, CFG_TUD_AUDIO_FUNC_1_FORMAT_2_EP_SZ_OUT) // Maximum EP IN size for all AS alternate settings used +#define CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ (TUD_OPT_HIGH_SPEED ? 32 : 4) * CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX // Example read FIFO every 1ms, so it should be 8 times larger for HS device // Number of Standard AS Interface Descriptors (4.9.1) defined per audio function - this is required to be able to remember the current alternate settings of these interfaces - We restrict us here to have a constant number for all audio functions (which means this has to be the maximum number of AS interfaces an audio function has and a second audio function with less AS interfaces just wastes a few bytes) #define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 2 diff --git a/examples/device/uac2_speaker_fb/src/main.c b/examples/device/uac2_speaker_fb/src/main.c index ea5a2941d..12425b919 100644 --- a/examples/device/uac2_speaker_fb/src/main.c +++ b/examples/device/uac2_speaker_fb/src/main.c @@ -27,12 +27,12 @@ #include #include "bsp/board_api.h" +#include "common_types.h" #include "tusb.h" #include "usb_descriptors.h" -#include "common_types.h" #ifdef CFG_QUIRK_OS_GUESSING -#include "quirk_os_guessing.h" + #include "quirk_os_guessing.h" #endif //--------------------------------------------------------------------+ @@ -41,14 +41,14 @@ // List of supported sample rates #if defined(__RX__) - const uint32_t sample_rates[] = {44100, 48000}; +const uint32_t sample_rates[] = {44100, 48000}; #else - const uint32_t sample_rates[] = {44100, 48000, 88200, 96000}; +const uint32_t sample_rates[] = {44100, 48000, 88200, 96000}; #endif -uint32_t current_sample_rate = 44100; +uint32_t current_sample_rate = 44100; -#define N_SAMPLE_RATES TU_ARRAY_SIZE(sample_rates) +#define N_SAMPLE_RATES TU_ARRAY_SIZE(sample_rates) /* Blink pattern * - 25 ms : streaming data @@ -56,16 +56,14 @@ uint32_t current_sample_rate = 44100; * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum -{ +enum { BLINK_STREAMING = 25, BLINK_NOT_MOUNTED = 250, BLINK_MOUNTED = 1000, BLINK_SUSPENDED = 2500, }; -enum -{ +enum { VOLUME_CTRL_0_DB = 0, VOLUME_CTRL_10_DB = 2560, VOLUME_CTRL_20_DB = 5120, @@ -84,11 +82,11 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; // Audio controls // Current states -int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 -int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 +int8_t mute[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1]; // +1 for master channel 0 +int16_t volume[CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1];// +1 for master channel 0 // Buffer for speaker data -uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ/2]; +uint16_t i2s_dummy_buffer[CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ / 2]; void led_blinking_task(void); void audio_task(void); @@ -96,20 +94,18 @@ void audio_task(void); #if CFG_AUDIO_DEBUG void audio_debug_task(void); uint8_t current_alt_settings; -uint16_t fifo_count; -uint32_t fifo_count_avg; +volatile uint16_t fifo_count; +volatile uint32_t fifo_count_avg; #endif /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); if (board_init_after_tusb) { @@ -118,9 +114,8 @@ int main(void) TU_LOG1("Speaker running\r\n"); - while (1) - { - tud_task(); // TinyUSB device task + while (1) { + tud_task();// TinyUSB device task led_blinking_task(); #if CFG_AUDIO_DEBUG audio_debug_task(); @@ -134,29 +129,25 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ - (void)remote_wakeup_en; +void tud_suspend_cb(bool remote_wakeup_en) { + (void) remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } @@ -165,43 +156,34 @@ void tud_resume_cb(void) //--------------------------------------------------------------------+ // Helper for clock get requests -static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request) -{ +static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t const *request) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); - if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) - { - if (request->bRequest == AUDIO_CS_REQ_CUR) - { + if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) { + if (request->bRequest == AUDIO_CS_REQ_CUR) { TU_LOG1("Clock get current freq %lu\r\n", current_sample_rate); - audio_control_cur_4_t curf = { (int32_t) tu_htole32(current_sample_rate) }; - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &curf, sizeof(curf)); - } - else if (request->bRequest == AUDIO_CS_REQ_RANGE) - { + audio_control_cur_4_t curf = {(int32_t) tu_htole32(current_sample_rate)}; + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &curf, sizeof(curf)); + } else if (request->bRequest == AUDIO_CS_REQ_RANGE) { audio_control_range_4_n_t(N_SAMPLE_RATES) rangef = - { - .wNumSubRanges = tu_htole16(N_SAMPLE_RATES) - }; + { + .wNumSubRanges = tu_htole16(N_SAMPLE_RATES)}; TU_LOG1("Clock get %d freq ranges\r\n", N_SAMPLE_RATES); - for(uint8_t i = 0; i < N_SAMPLE_RATES; i++) - { + for (uint8_t i = 0; i < N_SAMPLE_RATES; i++) { rangef.subrange[i].bMin = (int32_t) sample_rates[i]; rangef.subrange[i].bMax = (int32_t) sample_rates[i]; rangef.subrange[i].bRes = 0; - TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int)rangef.subrange[i].bMin, (int)rangef.subrange[i].bMax, (int)rangef.subrange[i].bRes); + TU_LOG1("Range %d (%d, %d, %d)\r\n", i, (int) rangef.subrange[i].bMin, (int) rangef.subrange[i].bMax, (int) rangef.subrange[i].bRes); } - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &rangef, sizeof(rangef)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &rangef, sizeof(rangef)); } - } - else if (request->bControlSelector == AUDIO_CS_CTRL_CLK_VALID && - request->bRequest == AUDIO_CS_REQ_CUR) - { - audio_control_cur_1_t cur_valid = { .bCur = 1 }; + } else if (request->bControlSelector == AUDIO_CS_CTRL_CLK_VALID && + request->bRequest == AUDIO_CS_REQ_CUR) { + audio_control_cur_1_t cur_valid = {.bCur = 1}; TU_LOG1("Clock get is valid %u\r\n", cur_valid.bCur); - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_valid, sizeof(cur_valid)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &cur_valid, sizeof(cur_valid)); } TU_LOG1("Clock get request not supported, entity = %u, selector = %u, request = %u\r\n", request->bEntityID, request->bControlSelector, request->bRequest); @@ -209,25 +191,21 @@ static bool tud_audio_clock_get_request(uint8_t rhport, audio_control_request_t } // Helper for clock set requests -static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) -{ - (void)rhport; +static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) { + (void) rhport; TU_ASSERT(request->bEntityID == UAC2_ENTITY_CLOCK); TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); - if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) - { + if (request->bControlSelector == AUDIO_CS_CTRL_SAM_FREQ) { TU_VERIFY(request->wLength == sizeof(audio_control_cur_4_t)); - current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *)buf)->bCur; + current_sample_rate = (uint32_t) ((audio_control_cur_4_t const *) buf)->bCur; TU_LOG1("Clock set current freq: %ld\r\n", current_sample_rate); return true; - } - else - { + } else { TU_LOG1("Clock set request not supported, entity = %u, selector = %u, request = %u\r\n", request->bEntityID, request->bControlSelector, request->bRequest); return false; @@ -235,33 +213,25 @@ static bool tud_audio_clock_set_request(uint8_t rhport, audio_control_request_t } // Helper for feature unit get requests -static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request) -{ +static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_request_t const *request) { TU_ASSERT(request->bEntityID == UAC2_ENTITY_FEATURE_UNIT); - if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR) - { - audio_control_cur_1_t mute1 = { .bCur = mute[request->bChannelNumber] }; + if (request->bControlSelector == AUDIO_FU_CTRL_MUTE && request->bRequest == AUDIO_CS_REQ_CUR) { + audio_control_cur_1_t mute1 = {.bCur = mute[request->bChannelNumber]}; TU_LOG1("Get channel %u mute %d\r\n", request->bChannelNumber, mute1.bCur); - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &mute1, sizeof(mute1)); - } - else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) - { - if (request->bRequest == AUDIO_CS_REQ_RANGE) - { + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &mute1, sizeof(mute1)); + } else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) { + if (request->bRequest == AUDIO_CS_REQ_RANGE) { audio_control_range_2_n_t(1) range_vol = { - .wNumSubRanges = tu_htole16(1), - .subrange[0] = { .bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256) } - }; + .wNumSubRanges = tu_htole16(1), + .subrange[0] = {.bMin = tu_htole16(-VOLUME_CTRL_50_DB), tu_htole16(VOLUME_CTRL_0_DB), tu_htole16(256)}}; TU_LOG1("Get channel %u volume range (%d, %d, %u) dB\r\n", request->bChannelNumber, range_vol.subrange[0].bMin / 256, range_vol.subrange[0].bMax / 256, range_vol.subrange[0].bRes / 256); - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &range_vol, sizeof(range_vol)); - } - else if (request->bRequest == AUDIO_CS_REQ_CUR) - { - audio_control_cur_2_t cur_vol = { .bCur = tu_htole16(volume[request->bChannelNumber]) }; + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &range_vol, sizeof(range_vol)); + } else if (request->bRequest == AUDIO_CS_REQ_CUR) { + audio_control_cur_2_t cur_vol = {.bCur = tu_htole16(volume[request->bChannelNumber])}; TU_LOG1("Get channel %u volume %d dB\r\n", request->bChannelNumber, cur_vol.bCur / 256); - return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *)request, &cur_vol, sizeof(cur_vol)); + return tud_audio_buffer_and_schedule_control_xfer(rhport, (tusb_control_request_t const *) request, &cur_vol, sizeof(cur_vol)); } } TU_LOG1("Feature unit get request not supported, entity = %u, selector = %u, request = %u\r\n", @@ -271,35 +241,29 @@ static bool tud_audio_feature_unit_get_request(uint8_t rhport, audio_control_req } // Helper for feature unit set requests -static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) -{ - (void)rhport; +static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_request_t const *request, uint8_t const *buf) { + (void) rhport; TU_ASSERT(request->bEntityID == UAC2_ENTITY_FEATURE_UNIT); TU_VERIFY(request->bRequest == AUDIO_CS_REQ_CUR); - if (request->bControlSelector == AUDIO_FU_CTRL_MUTE) - { + if (request->bControlSelector == AUDIO_FU_CTRL_MUTE) { TU_VERIFY(request->wLength == sizeof(audio_control_cur_1_t)); - mute[request->bChannelNumber] = ((audio_control_cur_1_t const *)buf)->bCur; + mute[request->bChannelNumber] = ((audio_control_cur_1_t const *) buf)->bCur; TU_LOG1("Set channel %d Mute: %d\r\n", request->bChannelNumber, mute[request->bChannelNumber]); return true; - } - else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) - { + } else if (request->bControlSelector == AUDIO_FU_CTRL_VOLUME) { TU_VERIFY(request->wLength == sizeof(audio_control_cur_2_t)); - volume[request->bChannelNumber] = ((audio_control_cur_2_t const *)buf)->bCur; + volume[request->bChannelNumber] = ((audio_control_cur_2_t const *) buf)->bCur; TU_LOG1("Set channel %d volume: %d dB\r\n", request->bChannelNumber, volume[request->bChannelNumber] / 256); return true; - } - else - { + } else { TU_LOG1("Feature unit set request not supported, entity = %u, selector = %u, request = %u\r\n", request->bEntityID, request->bControlSelector, request->bRequest); return false; @@ -307,16 +271,14 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio_control_req } // Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) -{ - audio_control_request_t const *request = (audio_control_request_t const *)p_request; +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + audio_control_request_t const *request = (audio_control_request_t const *) p_request; if (request->bEntityID == UAC2_ENTITY_CLOCK) return tud_audio_clock_get_request(rhport, request); if (request->bEntityID == UAC2_ENTITY_FEATURE_UNIT) return tud_audio_feature_unit_get_request(rhport, request); - else - { + else { TU_LOG1("Get request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); } @@ -324,9 +286,8 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p } // Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) -{ - audio_control_request_t const *request = (audio_control_request_t const *)p_request; +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) { + audio_control_request_t const *request = (audio_control_request_t const *) p_request; if (request->bEntityID == UAC2_ENTITY_FEATURE_UNIT) return tud_audio_feature_unit_set_request(rhport, request, buf); @@ -338,28 +299,26 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p return false; } -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void)rhport; +bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); if (ITF_NUM_AUDIO_STREAMING == itf && alt == 0) - blink_interval_ms = BLINK_MOUNTED; + blink_interval_ms = BLINK_MOUNTED; return true; } -bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request) -{ - (void)rhport; +bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_request) { + (void) rhport; uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); TU_LOG2("Set interface %d alt %d\r\n", itf, alt); if (ITF_NUM_AUDIO_STREAMING == itf && alt != 0) - blink_interval_ms = BLINK_STREAMING; + blink_interval_ms = BLINK_STREAMING; #if CFG_AUDIO_DEBUG current_alt_settings = alt; @@ -368,37 +327,34 @@ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_reque return true; } -void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param) -{ - (void)func_id; - (void)alt_itf; +void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t *feedback_param) { + (void) func_id; + (void) alt_itf; // Set feedback method to fifo counting feedback_param->method = AUDIO_FEEDBACK_METHOD_FIFO_COUNT; feedback_param->sample_freq = current_sample_rate; } #if CFG_AUDIO_DEBUG -bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting) -{ - (void)rhport; - (void)n_bytes_received; - (void)func_id; - (void)ep_out; - (void)cur_alt_setting; +bool tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting) { + (void) rhport; + (void) n_bytes_received; + (void) func_id; + (void) ep_out; + (void) cur_alt_setting; fifo_count = tud_audio_available(); // Same averaging method used in UAC2 class - fifo_count_avg = (uint32_t)(((uint64_t)fifo_count_avg * 63 + ((uint32_t)fifo_count << 16)) >> 6); + fifo_count_avg = (uint32_t) (((uint64_t) fifo_count_avg * 63 + ((uint32_t) fifo_count << 16)) >> 6); return true; } #endif #if CFG_QUIRK_OS_GUESSING -bool tud_audio_feedback_format_correction_cb(uint8_t func_id) -{ - (void)func_id; - if(tud_speed_get() == TUSB_SPEED_FULL && quirk_os_guessing_get() == QUIRK_OS_GUESSING_OSX) { +bool tud_audio_feedback_format_correction_cb(uint8_t func_id) { + (void) func_id; + if (tud_speed_get() == TUSB_SPEED_FULL && quirk_os_guessing_get() == QUIRK_OS_GUESSING_OSX) { return true; } else { return false; @@ -409,25 +365,21 @@ bool tud_audio_feedback_format_correction_cb(uint8_t func_id) // AUDIO Task //--------------------------------------------------------------------+ -void audio_task(void) -{ - // Replace audio_task() with your I2S transmit callback. - // Here we simulate a callback called every 1ms. +// This task simulates an audio transmit callback, one frame is sent every 1ms. +// In a real application, this would be replaced with actual I2S transmit callback. +void audio_task(void) { static uint32_t start_ms = 0; uint32_t curr_ms = board_millis(); - if ( start_ms == curr_ms ) return; // not enough time + if (start_ms == curr_ms) return;// not enough time start_ms = curr_ms; - uint16_t length = (uint16_t) (current_sample_rate/1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX); + uint16_t length = (uint16_t) (current_sample_rate / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX); - if (current_sample_rate == 44100 && (curr_ms % 10 == 0)) - { + if (current_sample_rate == 44100 && (curr_ms % 10 == 0)) { // Take one more sample every 10 cycles, to have a average reading speed of 44.1 // This correction is not needed in real world cases length += CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX; - } else - if (current_sample_rate == 88200 && (curr_ms % 5 == 0)) - { + } else if (current_sample_rate == 88200 && (curr_ms % 5 == 0)) { // Take one more sample every 5 cycles, to have a average reading speed of 88.2 // This correction is not needed in real world cases length += CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_RX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX; @@ -439,8 +391,7 @@ void audio_task(void) //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; @@ -457,33 +408,30 @@ void led_blinking_task(void) // HID interface for audio debug //--------------------------------------------------------------------+ // Every 1ms, we will sent 1 debug information report -void audio_debug_task(void) -{ +void audio_debug_task(void) { static uint32_t start_ms = 0; uint32_t curr_ms = board_millis(); - if ( start_ms == curr_ms ) return; // not enough time + if (start_ms == curr_ms) return;// not enough time start_ms = curr_ms; audio_debug_info_t debug_info; - debug_info.sample_rate = current_sample_rate; - debug_info.alt_settings = current_alt_settings; - debug_info.fifo_size = CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ; - debug_info.fifo_count = fifo_count; + debug_info.sample_rate = current_sample_rate; + debug_info.alt_settings = current_alt_settings; + debug_info.fifo_size = CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ; + debug_info.fifo_count = fifo_count; debug_info.fifo_count_avg = (uint16_t) (fifo_count_avg >> 16); - for (int i = 0; i < CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1; i++) - { + for (int i = 0; i < CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_RX + 1; i++) { debug_info.mute[i] = mute[i]; debug_info.volume[i] = volume[i]; } - if(tud_hid_ready()) + if (tud_hid_ready()) tud_hid_report(0, &debug_info, sizeof(debug_info)); } // Invoked when received GET_REPORT control request // Unused here -uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) -{ +uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) { // TODO not Implemented (void) itf; (void) report_id; @@ -496,8 +444,7 @@ uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t // Invoked when received SET_REPORT control request or // Unused here -void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) -{ +void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) { // This example doesn't use multiple report and report ID (void) itf; (void) report_id; From d4abf43f226b5594c935c60c38d05a90359763e1 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 17 Jun 2025 22:16:13 +0700 Subject: [PATCH 228/382] add common cdch_process_set_config() to safely complete set_config() when it failed. driver_process_set_config() also pass drv index with user_data --- examples/host/cdc_msc_hid/src/cdc_app.c | 13 +- src/class/cdc/cdc_host.c | 887 ++++++++++++------------ 2 files changed, 453 insertions(+), 447 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index e68ec383b..6f4433f22 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -31,8 +31,7 @@ static size_t get_console_inputs(uint8_t* buf, size_t bufsize) { size_t count = 0; while (count < bufsize) { int ch = board_getchar(); - if (ch <= 0) break; - + if (ch <= 0) { break; } buf[count] = (uint8_t) ch; count++; } @@ -69,10 +68,12 @@ void tuh_cdc_rx_cb(uint8_t idx) { uint32_t const bufsize = sizeof(buf) - 1; // forward cdc interfaces -> console - uint32_t count = tuh_cdc_read(idx, buf, bufsize); - buf[count] = 0; - - printf("%s", (char*) buf); + const uint32_t count = tuh_cdc_read(idx, buf, bufsize); + if (count) { + buf[count] = 0; + printf("%s", (char*) buf); + fflush(stdout); + } } // Invoked when a device with CDC interface is mounted diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 5d5da9796..b6e9cb297 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -52,17 +52,6 @@ serial_drivers[p_cdc->serial_drid].name, ##__VA_ARGS__) #define TU_LOG_P_CDC_BOOL(TXT,VAL) TU_LOG_P_CDC(TXT " " #VAL " = %d", VAL) -// assert and set config complete -#define TU_ASSERT_COMPLETE_DEFINE(_cond, _itf_offset) \ - do { \ - if (!(_cond)) { _MESS_FAILED(); TU_BREAKPOINT(); set_config_complete(idx, _itf_offset, false); } \ - } while(0) - -#define TU_ASSERT_COMPLETE_1ARGS(_cond) TU_ASSERT_COMPLETE_DEFINE(_cond, 0) -#define TU_ASSERT_COMPLETE_2ARGS(_cond, _itf_offset) TU_ASSERT_COMPLETE_DEFINE(_cond, _itf_offset) - -#define TU_ASSERT_COMPLETE(...) _GET_3RD_ARG(__VA_ARGS__, TU_ASSERT_COMPLETE_2ARGS, TU_ASSERT_COMPLETE_1ARGS, _dummy)(__VA_ARGS__) - // handle line control defines #if defined(CFG_TUH_CDC_LINE_CONTROL_ON_ENUM) && \ (defined(CFG_TUH_CDC_DTR_CONTROL_ON_ENUM) || defined(CFG_TUH_CDC_RTS_CONTROL_ON_ENUM)) @@ -142,9 +131,14 @@ CFG_TUH_MEM_SECTION static cdch_epbuf_t cdch_epbuf[CFG_TUH_CDC]; // Serial Driver //--------------------------------------------------------------------+ +// for process_set_config user_data: idx (byte1) and state (byte0) +#define PROCESS_CONFIG_STATE(_idx, _state) tu_u16(_idx, _state) + +static void cdch_process_set_config(tuh_xfer_t *xfer); + //------------- ACM prototypes -------------// static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static void acm_process_config(tuh_xfer_t * xfer); +static bool acm_process_set_config(tuh_xfer_t * xfer); static bool acm_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -159,7 +153,7 @@ static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST}; #endif static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); -static void ftdi_process_config(tuh_xfer_t * xfer); +static bool ftdi_proccess_set_config(tuh_xfer_t * xfer); static bool ftdi_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ftdi_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -172,7 +166,7 @@ static bool ftdi_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIST}; static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static void cp210x_process_config(tuh_xfer_t * xfer); +static bool cp210x_process_set_config(tuh_xfer_t * xfer); static bool cp210x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool cp210x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -185,7 +179,7 @@ static bool cp210x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t comple static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST}; static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static void ch34x_process_config(tuh_xfer_t * xfer); +static bool ch34x_process_set_config(tuh_xfer_t *xfer); static bool ch34x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ch34x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -201,7 +195,7 @@ static const struct pl2303_type_data pl2303_type_data[TYPE_COUNT] = {PL2303_TYPE CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static void pl2303_process_config(tuh_xfer_t * xfer); +static bool pl2303_process_set_config(tuh_xfer_t *xfer); static bool pl2303_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool pl2303_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -236,7 +230,7 @@ typedef struct { uint16_t const (*vid_pid_list)[2]; uint16_t const vid_pid_count; bool (*const open)(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); - void (*const process_set_config)(tuh_xfer_t * xfer); + bool (*const process_set_config)(tuh_xfer_t * xfer); bool (*const set_control_line_state)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); bool (*const set_baudrate)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); bool (*const set_data_format)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -252,7 +246,7 @@ static const cdch_serial_driver_t serial_drivers[] = { .vid_pid_list = NULL, .vid_pid_count = 0, .open = acm_open, - .process_set_config = acm_process_config, + .process_set_config = acm_process_set_config, .set_control_line_state = acm_set_control_line_state, .set_baudrate = acm_set_baudrate, .set_data_format = acm_set_data_format, @@ -267,7 +261,7 @@ static const cdch_serial_driver_t serial_drivers[] = { .vid_pid_list = ftdi_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(ftdi_vid_pid_list), .open = ftdi_open, - .process_set_config = ftdi_process_config, + .process_set_config = ftdi_proccess_set_config, .set_control_line_state = ftdi_set_modem_ctrl, .set_baudrate = ftdi_set_baudrate, .set_data_format = ftdi_set_data_format, @@ -283,7 +277,7 @@ static const cdch_serial_driver_t serial_drivers[] = { .vid_pid_list = cp210x_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(cp210x_vid_pid_list), .open = cp210x_open, - .process_set_config = cp210x_process_config, + .process_set_config = cp210x_process_set_config, .set_control_line_state = cp210x_set_modem_ctrl, .set_baudrate = cp210x_set_baudrate, .set_data_format = cp210x_set_data_format, @@ -299,7 +293,7 @@ static const cdch_serial_driver_t serial_drivers[] = { .vid_pid_list = ch34x_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(ch34x_vid_pid_list), .open = ch34x_open, - .process_set_config = ch34x_process_config, + .process_set_config = ch34x_process_set_config, .set_control_line_state = ch34x_set_modem_ctrl, .set_baudrate = ch34x_set_baudrate, .set_data_format = ch34x_set_data_format, @@ -315,7 +309,7 @@ static const cdch_serial_driver_t serial_drivers[] = { .vid_pid_list = pl2303_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(pl2303_vid_pid_list), .open = pl2303_open, - .process_set_config = pl2303_process_config, + .process_set_config = pl2303_process_set_config, .set_control_line_state = pl2303_set_modem_ctrl, .set_baudrate = pl2303_set_baudrate, .set_data_format = pl2303_set_data_format, @@ -378,9 +372,8 @@ static bool open_ep_stream_pair(cdch_interface_t * p_cdc , tusb_desc_endpoint_t uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num) { for (uint8_t i = 0; i < CFG_TUH_CDC; i++) { const cdch_interface_t * p_cdc = &cdch_data[i]; - if (p_cdc->daddr == daddr && p_cdc->bInterfaceNumber == itf_num) return i; + if (p_cdc->daddr == daddr && p_cdc->bInterfaceNumber == itf_num) { return i; } } - return TUSB_INDEX_INVALID_8; } @@ -642,18 +635,18 @@ bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, uin } bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t * p_cdc = get_itf(idx); + cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - cdc_line_control_state_t const line_state = { .rts = rts_state, .dtr = p_cdc->line_state.dtr }; + cdc_line_control_state_t const line_state = {.rts = rts_state, .dtr = p_cdc->line_state.dtr}; return tuh_cdc_set_control_line_state_u(idx, line_state, complete_cb, user_data); } bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t * p_cdc = get_itf(idx); + cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); TU_LOG_P_CDC("set baudrate %lu", baudrate); - cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; + cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line_coding.bit_rate = baudrate; @@ -669,12 +662,12 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t * p_cdc = get_itf(idx); + cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); TU_LOG_P_CDC("set data format %u%c%s", data_bits, CDC_LINE_CODING_PARITY_CHAR(parity), CDC_LINE_CODING_STOP_BITS_TEXT(stop_bits)); - cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; + cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line_coding.stop_bits = stop_bits; p_cdc->requested_line_coding.parity = parity; @@ -692,15 +685,15 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin return ret; } -bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const * line_coding, +bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t * p_cdc = get_itf(idx); + cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); TU_LOG_P_CDC("set line coding %lu %u%c%s", line_coding->bit_rate, line_coding->data_bits, CDC_LINE_CODING_PARITY_CHAR(line_coding->parity), CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); - cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; + cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line_coding = *line_coding; @@ -722,8 +715,8 @@ bool cdch_init(void) { TU_LOG_DRV("sizeof(cdch_interface_t) = %u\r\n", sizeof(cdch_interface_t)); tu_memclr(cdch_data, sizeof(cdch_data)); for (size_t i = 0; i < CFG_TUH_CDC; i++) { - cdch_interface_t* p_cdc = &cdch_data[i]; - cdch_epbuf_t* epbuf = &cdch_epbuf[i]; + cdch_interface_t *p_cdc = &cdch_data[i]; + cdch_epbuf_t *epbuf = &cdch_epbuf[i]; tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, epbuf->tx, CFG_TUH_CDC_TX_EPSIZE); @@ -738,7 +731,7 @@ bool cdch_init(void) { bool cdch_deinit(void) { for (size_t i = 0; i < CFG_TUH_CDC; i++) { - cdch_interface_t* p_cdc = &cdch_data[i]; + cdch_interface_t *p_cdc = &cdch_data[i]; tu_edpt_stream_deinit(&p_cdc->stream.tx); tu_edpt_stream_deinit(&p_cdc->stream.rx); } @@ -747,7 +740,7 @@ bool cdch_deinit(void) { void cdch_close(uint8_t daddr) { for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { - cdch_interface_t * p_cdc = &cdch_data[idx]; + cdch_interface_t *p_cdc = &cdch_data[idx]; if (p_cdc->daddr == daddr) { TU_LOG_P_CDC("close"); @@ -770,7 +763,7 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t TU_VERIFY(event == XFER_RESULT_SUCCESS); uint8_t const idx = get_idx_by_ep_addr(daddr, ep_addr); - cdch_interface_t * p_cdc = get_itf(idx); + cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc); if (ep_addr == p_cdc->stream.tx.ep_addr) { @@ -779,31 +772,36 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t tuh_cdc_tx_complete_cb(idx); } - if ( 0 == tu_edpt_stream_write_xfer(daddr, &p_cdc->stream.tx) ) { + if (0 == tu_edpt_stream_write_xfer(daddr, &p_cdc->stream.tx)) { // If there is no data left, a ZLP should be sent if: // - xferred_bytes is multiple of EP Packet size and not zero tu_edpt_stream_write_zlp_if_needed(daddr, &p_cdc->stream.tx, xferred_bytes); } } else if (ep_addr == p_cdc->stream.rx.ep_addr) { #if CFG_TUH_CDC_FTDI - if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI && xferred_bytes > 2) { + if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI) { // FTDI reserve 2 bytes for status // uint8_t status[2] = {p_cdc->stream.rx.ep_buf[0], p_cdc->stream.rx.ep_buf[1]}; - tu_edpt_stream_read_xfer_complete_with_buf(&p_cdc->stream.rx, p_cdc->stream.rx.ep_buf+2, xferred_bytes-2); - }else + if (xferred_bytes > 2) { + tu_edpt_stream_read_xfer_complete_with_buf(&p_cdc->stream.rx, p_cdc->stream.rx.ep_buf + 2, xferred_bytes - 2); + + if (tuh_cdc_rx_cb) { + tuh_cdc_rx_cb(idx); // invoke receive callback + } + } + } else #endif { tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); - } - // invoke receive callback - if (tuh_cdc_rx_cb) { - tuh_cdc_rx_cb(idx); + if (tuh_cdc_rx_cb) { + tuh_cdc_rx_cb(idx); // invoke receive callback + } } // prepare for next transfer if needed tu_edpt_stream_read_xfer(daddr, &p_cdc->stream.rx); - }else if ( ep_addr == p_cdc->ep_notif ) { + } else if (ep_addr == p_cdc->ep_notif) { // TODO handle notification endpoint } else { TU_ASSERT(false); @@ -816,7 +814,7 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t // Enumeration //--------------------------------------------------------------------+ -static bool open_ep_stream_pair(cdch_interface_t * p_cdc, tusb_desc_endpoint_t const * desc_ep) { +static bool open_ep_stream_pair(cdch_interface_t *p_cdc, tusb_desc_endpoint_t const *desc_ep) { for (size_t i = 0; i < 2; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); @@ -834,9 +832,9 @@ static bool open_ep_stream_pair(cdch_interface_t * p_cdc, tusb_desc_endpoint_t c return true; } -bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { +bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; - cdch_serial_driver_t const * driver_detected = NULL; + cdch_serial_driver_t const *driver_detected = NULL; // For CDC: only support ACM subclass // Note: Protocol 0xFF can be RNDIS device @@ -849,7 +847,7 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const * itf_ TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); for (size_t dr = 1; dr < SERIAL_DRIVER_COUNT; dr++) { - cdch_serial_driver_t const * driver = &serial_drivers[dr]; + cdch_serial_driver_t const *driver = &serial_drivers[dr]; for (size_t i = 0; i < driver->vid_pid_count; i++) { if (driver->vid_pid_list[i][0] == vid && driver->vid_pid_list[i][1] == pid) { driver_detected = driver; @@ -865,7 +863,7 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const * itf_ if (driver_detected) { TU_LOG_CDC("open", daddr, itf_desc->bInterfaceNumber, driver_detected->name); bool ret = driver_detected->open(daddr, itf_desc, max_len); -// TU_LOG_CDC("opened ret = %s", daddr, itf_desc->bInterfaceNumber, driver_detected->name, ret ? "true" : "FALSE" ); + // TU_LOG_CDC("opened ret = %s", daddr, itf_desc->bInterfaceNumber, driver_detected->name, ret ? "true" : "FALSE" ); return ret; } @@ -873,8 +871,8 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const * itf_ } static void set_config_complete(uint8_t idx, uint8_t itf_offset, bool success) { - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); + cdch_interface_t *p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); TU_LOG_P_CDC_BOOL("set config complete", success); if (success) { @@ -894,22 +892,32 @@ static void set_config_complete(uint8_t idx, uint8_t itf_offset, bool success) { usbh_driver_set_config_complete(p_cdc->daddr, p_cdc->bInterfaceNumber + itf_offset); } +static void cdch_process_set_config(tuh_xfer_t *xfer) { + const uint8_t idx = tu_u32_byte1(xfer->user_data); + cdch_interface_t *p_cdc = get_itf(idx); + TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); + + if (!serial_drivers[p_cdc->serial_drid].process_set_config(xfer)) { + const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; + set_config_complete(idx, itf_offset, false); + } +} + bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { tusb_control_request_t request; request.wIndex = tu_htole16((uint16_t) itf_num); uint8_t const idx = tuh_cdc_itf_get_index(daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); + cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); TU_LOG_P_CDC("set config"); // fake transfer to kick-off process_set_config() tuh_xfer_t xfer; - xfer.daddr = daddr; + xfer.daddr = daddr; xfer.result = XFER_RESULT_SUCCESS; - xfer.setup = &request; - xfer.user_data = 0; // initial state 0 - - serial_drivers[p_cdc->serial_drid].process_set_config(&xfer); + xfer.setup = &request; + xfer.user_data = PROCESS_CONFIG_STATE(idx, 0); // initial state 0 + cdch_process_set_config(&xfer); return true; } @@ -921,11 +929,11 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { //------------- Driver API -------------// // internal control complete to update state such as line state, encoding -static void acm_internal_control_complete(tuh_xfer_t * xfer) { +static void acm_internal_control_complete(tuh_xfer_t *xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); + cdch_interface_t *p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); TU_LOG_P_CDC_BOOL("control complete", success); @@ -949,7 +957,7 @@ static void acm_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool acm_set_control_line_state(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); tusb_control_request_t const request = { @@ -980,10 +988,10 @@ static bool acm_set_control_line_state(cdch_interface_t * p_cdc, tuh_xfer_cb_t c return true; } -static bool acm_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm_capability.support_line_request); TU_VERIFY((p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8) || - p_cdc->requested_line_coding.data_bits == 16); + p_cdc->requested_line_coding.data_bits == 16); tusb_control_request_t const request = { .bmRequestType_bit = { @@ -998,7 +1006,7 @@ static bool acm_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete }; // use usbh enum buf to hold line coding since user line_coding variable does not live long enough - uint8_t * enum_buf = usbh_get_enum_buf(); + uint8_t *enum_buf = usbh_get_enum_buf(); memcpy(enum_buf, &p_cdc->requested_line_coding, sizeof(cdc_line_coding_t)); p_cdc->user_control_cb = complete_cb; @@ -1017,13 +1025,13 @@ static bool acm_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete return true; } -static bool acm_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->requested_line_coding.bit_rate = p_cdc->line_coding.bit_rate; return acm_set_line_coding(p_cdc, complete_cb, user_data); } -static bool acm_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool acm_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->requested_line_coding.stop_bits = p_cdc->line_coding.stop_bits; p_cdc->requested_line_coding.parity = p_cdc->line_coding.parity; p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits; @@ -1036,19 +1044,19 @@ static bool acm_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb enum { CONFIG_ACM_SET_CONTROL_LINE_STATE = 0, CONFIG_ACM_SET_LINE_CODING, - CONFIG_ACM_COMPLETE, + CONFIG_ACM_COMPLETE }; -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { - uint8_t const * p_desc_end = ((uint8_t const *) itf_desc) + max_len; +static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { + uint8_t const *p_desc_end = ((uint8_t const *) itf_desc) + max_len; - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); + cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); p_cdc->serial_drid = SERIAL_DRIVER_ACM; //------------- Control Interface -------------// - uint8_t const * p_desc = tu_desc_next(itf_desc); + uint8_t const *p_desc = tu_desc_next(itf_desc); // Communication Functional Descriptors while ((p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) { @@ -1063,7 +1071,7 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint // Open notification endpoint of control interface if any if (itf_desc->bNumEndpoints == 1) { TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc; + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); p_cdc->ep_notif = desc_ep->bEndpointAddress; @@ -1084,31 +1092,31 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint return true; } -static void acm_process_config(tuh_xfer_t * xfer) { - uintptr_t const state = xfer->user_data; +static bool acm_process_set_config(tuh_xfer_t *xfer) { + const uint8_t state = (uint8_t) xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS, 1); + cdch_interface_t *p_cdc = get_itf(idx); + TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); switch (state) { case CONFIG_ACM_SET_CONTROL_LINE_STATE: #ifdef LINE_CONTROL_ON_ENUM - if (p_cdc->acm_capability.support_line_request) { - p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; - TU_ASSERT_COMPLETE(acm_set_control_line_state(p_cdc, acm_process_config, CONFIG_ACM_SET_LINE_CODING), 1); - break; - } + if (p_cdc->acm_capability.support_line_request) { + p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; + TU_ASSERT(acm_set_control_line_state(p_cdc, cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_ACM_SET_LINE_CODING))); + break; + } #endif TU_ATTR_FALLTHROUGH; case CONFIG_ACM_SET_LINE_CODING: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - if (p_cdc->acm_capability.support_line_request) { - p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT_COMPLETE(acm_set_line_coding(p_cdc, acm_process_config, CONFIG_ACM_COMPLETE), 1); - break; - } + if (p_cdc->acm_capability.support_line_request) { + p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + TU_ASSERT(acm_set_line_coding(p_cdc, cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_ACM_COMPLETE))); + break; + } #endif TU_ATTR_FALLTHROUGH; @@ -1118,9 +1126,10 @@ static void acm_process_config(tuh_xfer_t * xfer) { break; default: - set_config_complete(idx, 1, false); - break; + return false; // invalid state } + + return true; } //--------------------------------------------------------------------+ @@ -1128,14 +1137,14 @@ static void acm_process_config(tuh_xfer_t * xfer) { //--------------------------------------------------------------------+ #if CFG_TUH_CDC_FTDI -static bool ftdi_determine_type(cdch_interface_t * p_cdc); -static uint32_t ftdi_get_divisor(cdch_interface_t * p_cdc); -static uint8_t ftdi_get_idx(tuh_xfer_t * xfer); +static bool ftdi_determine_type(cdch_interface_t *p_cdc); +static uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc); +static uint8_t ftdi_get_idx(tuh_xfer_t *xfer); //------------- Control Request -------------// // set request without data -static bool ftdi_set_request(cdch_interface_t * p_cdc, uint8_t request, uint8_t requesttype, +static bool ftdi_set_request(cdch_interface_t *p_cdc, uint8_t request, uint8_t requesttype, uint16_t value, uint16_t index, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request_setup = { .bmRequestType = requesttype, @@ -1167,37 +1176,36 @@ static int8_t ftdi_write_latency_timer(cdch_interface_t * p_cdc, uint16_t latenc } #endif -static inline bool ftdi_sio_reset(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static inline bool ftdi_sio_reset(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ftdi_set_request(p_cdc, FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, FTDI_SIO_RESET_SIO, p_cdc->ftdi.channel, complete_cb, user_data); } -static bool ftdi_change_speed(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ftdi_change_speed(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint32_t index_value = ftdi_get_divisor(p_cdc); TU_VERIFY(index_value); uint16_t value = (uint16_t) index_value; uint16_t index = (uint16_t) (index_value >> 16); if (p_cdc->ftdi.channel) { - index = (uint16_t)((index << 8) | p_cdc->ftdi.channel); + index = (uint16_t) ((index << 8) | p_cdc->ftdi.channel); } return ftdi_set_request(p_cdc, FTDI_SIO_SET_BAUDRATE_REQUEST, FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, value, index, complete_cb, user_data); } -static bool ftdi_set_data_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ftdi_set_data_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 7 && p_cdc->requested_line_coding.data_bits <= 8, 0); - uint16_t value = (uint16_t) ( - (p_cdc->requested_line_coding.data_bits & 0xfUL) | // data bit quantity is stored in bits 0-3 - (p_cdc->requested_line_coding.parity & 0x7UL) << 8 | // parity is stored in bits 8-10, same coding - (p_cdc->requested_line_coding.stop_bits & 0x3UL) << 11 ); // stop bits quantity is stored in bits 11-12, same coding - // not each FTDI supports 1.5 stop bits + uint16_t value = (uint16_t) ((p_cdc->requested_line_coding.data_bits & 0xfUL) | // data bit quantity is stored in bits 0-3 + (p_cdc->requested_line_coding.parity & 0x7UL) << 8 | // parity is stored in bits 8-10, same coding + (p_cdc->requested_line_coding.stop_bits & 0x3UL) << 11); // stop bits quantity is stored in bits 11-12, same coding + // not each FTDI supports 1.5 stop bits return ftdi_set_request(p_cdc, FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, value, p_cdc->ftdi.channel, complete_cb, user_data); } -static inline bool ftdi_update_mctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static inline bool ftdi_update_mctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t value = (uint16_t) ((p_cdc->requested_line_state.dtr ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW) | (p_cdc->requested_line_state.rts ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW)); @@ -1208,10 +1216,10 @@ static inline bool ftdi_update_mctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t com //------------- Driver API -------------// // internal control complete to update state such as line state, line_coding -static void ftdi_internal_control_complete(tuh_xfer_t * xfer) { +static void ftdi_internal_control_complete(tuh_xfer_t *xfer) { uint8_t const idx = ftdi_get_idx(xfer); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); + cdch_interface_t *p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); TU_LOG_P_CDC_BOOL("control complete", success); @@ -1238,24 +1246,24 @@ static void ftdi_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool ftdi_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(ftdi_set_data_request(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); return true; } -static bool ftdi_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(ftdi_change_speed(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); return true; } -static void ftdi_set_line_coding_stage1_complete(tuh_xfer_t * xfer) { +static void ftdi_set_line_coding_stage1_complete(tuh_xfer_t *xfer) { uint8_t const idx = ftdi_get_idx(xfer); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); + cdch_interface_t *p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); uint8_t const itf_num = p_cdc->bInterfaceNumber; set_line_coding_stage1_complete(xfer, itf_num, ftdi_set_data_request, // control request function to set data format @@ -1272,7 +1280,7 @@ static bool ftdi_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complet complete_cb, user_data); } -static bool ftdi_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(ftdi_update_mctrl(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); @@ -1293,19 +1301,19 @@ enum { CONFIG_FTDI_COMPLETE }; -static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len) { +static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // FTDI Interface includes 1 vendor interface + 2 bulk endpoints TU_VERIFY(itf_desc->bInterfaceSubClass == 0xff && itf_desc->bInterfaceProtocol == 0xff && itf_desc->bNumEndpoints == 2); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) <= max_len); + TU_VERIFY(sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t) <= max_len); - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); + cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); p_cdc->serial_drid = SERIAL_DRIVER_FTDI; // endpoint pair - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); /* * NOTE: Some customers have programmed FT232R/FT245R devices @@ -1317,22 +1325,20 @@ static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uin return open_ep_stream_pair(p_cdc, desc_ep); } -static void ftdi_process_config(tuh_xfer_t * xfer) { - uintptr_t const state = xfer->user_data; +static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { + const uint8_t state = (uint8_t) xfer->user_data; uint8_t const idx = ftdi_get_idx(xfer); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS); + cdch_interface_t *p_cdc = get_itf(idx); uint8_t const itf_num = p_cdc->bInterfaceNumber; + TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); - switch(state) { - + switch (state) { // from here sequence overtaken from Linux Kernel function ftdi_port_probe() case CONFIG_FTDI_GET_DESC: // get device descriptor - p_cdc->user_control_cb = ftdi_process_config; // set once for whole process config - if (itf_num == 0) { // only necessary for 1st interface. other interface overtake type from interface 0 - TU_ASSERT_COMPLETE(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), - ftdi_process_config, CONFIG_FTDI_DETERMINE_TYPE)); + if (itf_num == 0) { // only necessary for 1st interface. other interface overtake type from interface 0 + TU_ASSERT(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_DETERMINE_TYPE))); break; } TU_ATTR_FALLTHROUGH; @@ -1340,66 +1346,67 @@ static void ftdi_process_config(tuh_xfer_t * xfer) { case CONFIG_FTDI_DETERMINE_TYPE: // determine type if (itf_num == 0) { - TU_ASSERT_COMPLETE(ftdi_determine_type(p_cdc)); + TU_ASSERT(ftdi_determine_type(p_cdc)); } else { // other interfaces have same type as interface 0 uint8_t const idx_itf0 = tuh_cdc_itf_get_index(xfer->daddr, 0); - cdch_interface_t const * p_cdc_itf0 = get_itf(idx_itf0); - TU_ASSERT_COMPLETE(p_cdc_itf0); - if (p_cdc_itf0) { - p_cdc->ftdi.chip_type = p_cdc_itf0->ftdi.chip_type; - } + cdch_interface_t const *p_cdc_itf0 = get_itf(idx_itf0); + TU_ASSERT(p_cdc_itf0); + p_cdc->ftdi.chip_type = p_cdc_itf0->ftdi.chip_type; } TU_ATTR_FALLTHROUGH; case CONFIG_FTDI_WRITE_LATENCY: #ifdef CFG_TUH_CDC_FTDI_LATENCY - int8_t result = ftdi_write_latency_timer(p_cdc, CFG_TUH_CDC_FTDI_LATENCY, ftdi_process_config, - CONFIG_FTDI_SIO_RESET); - TU_ASSERT_COMPLETE(result != FTDI_FAIL); - if(result == FTDI_REQUESTED) { - break; - } // else FTDI_NOT_POSSIBLE => continue directly with next state + int8_t result = ftdi_write_latency_timer(p_cdc, CFG_TUH_CDC_FTDI_LATENCY, ftdi_process_config, + CONFIG_FTDI_SIO_RESET); + TU_ASSERT(result != FTDI_FAIL); + if (result == FTDI_REQUESTED) { + break; + }// else FTDI_NOT_POSSIBLE => continue directly with next state #endif TU_ATTR_FALLTHROUGH; - // from here sequence overtaken from Linux Kernel function ftdi_open() + // from here sequence overtaken from Linux Kernel function ftdi_open() case CONFIG_FTDI_SIO_RESET: - TU_ASSERT_COMPLETE(ftdi_sio_reset(p_cdc, ftdi_process_config, CONFIG_FTDI_SET_DATA)); + p_cdc->user_control_cb = cdch_process_set_config; + TU_ASSERT(ftdi_sio_reset(p_cdc, cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_SET_DATA))); break; - // from here sequence overtaken from Linux Kernel function ftdi_set_termios() + // from here sequence overtaken from Linux Kernel function ftdi_set_termios() case CONFIG_FTDI_SET_DATA: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT_COMPLETE(ftdi_set_data_request(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_SET_BAUDRATE)); - break; + p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + p_cdc->user_control_cb = cdch_process_set_config; + TU_ASSERT(ftdi_set_data_request(p_cdc, ftdi_internal_control_complete, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_SET_BAUDRATE))); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif case CONFIG_FTDI_SET_BAUDRATE: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - TU_ASSERT_COMPLETE(ftdi_change_speed(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_FLOW_CONTROL)); - break; + p_cdc->user_control_cb = cdch_process_set_config; + TU_ASSERT(ftdi_change_speed(p_cdc, ftdi_internal_control_complete, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_FLOW_CONTROL))); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif case CONFIG_FTDI_FLOW_CONTROL: // disable flow control - TU_ASSERT_COMPLETE(ftdi_set_request(p_cdc, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - FTDI_SIO_DISABLE_FLOW_CTRL, p_cdc->ftdi.channel, - ftdi_process_config, CONFIG_FTDI_MODEM_CTRL)); + TU_ASSERT(ftdi_set_request(p_cdc, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, FTDI_SIO_DISABLE_FLOW_CTRL, + p_cdc->ftdi.channel, cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_MODEM_CTRL))); break; case CONFIG_FTDI_MODEM_CTRL: #ifdef LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; - TU_ASSERT_COMPLETE(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_COMPLETE)); - break; + p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; + p_cdc->user_control_cb = cdch_process_set_config; + TU_ASSERT(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_COMPLETE))); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif case CONFIG_FTDI_COMPLETE: @@ -1407,15 +1414,15 @@ static void ftdi_process_config(tuh_xfer_t * xfer) { break; default: - TU_ASSERT_COMPLETE(false); - break; + return false; } + + return true; } //------------- Helper -------------// -static bool ftdi_determine_type(cdch_interface_t * p_cdc) -{ +static bool ftdi_determine_type(cdch_interface_t *p_cdc) { uint16_t const version = desc_dev->bcdDevice; uint8_t const itf_num = p_cdc->bInterfaceNumber; @@ -1527,28 +1534,27 @@ static bool ftdi_determine_type(cdch_interface_t * p_cdc) //} static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { - uint8_t divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; + uint8_t divfrac[8] = {0, 3, 2, 4, 1, 5, 6, 7}; uint32_t divisor; /* divisor shifted 3 bits to the left */ uint32_t divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); divisor = divisor3 >> 3; - divisor |= (uint32_t)divfrac[divisor3 & 0x7] << 14; + divisor |= (uint32_t) divfrac[divisor3 & 0x7] << 14; /* Deal with special cases for highest baud rates. */ - if (divisor == 1) /* 1.0 */ + if (divisor == 1) /* 1.0 */ { divisor = 0; - else if (divisor == 0x4001) /* 1.5 */ + } else if (divisor == 0x4001) /* 1.5 */ { divisor = 1; + } return divisor; } -static inline uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) -{ - return ftdi_232bm_baud_base_to_divisor(baud, 48000000); +static inline uint32_t ftdi_232bm_baud_to_divisor(uint32_t baud) { + return ftdi_232bm_baud_base_to_divisor(baud, 48000000); } -static uint32_t ftdi_2232h_baud_base_to_divisor(uint32_t baud, uint32_t base) -{ - static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; +static uint32_t ftdi_2232h_baud_base_to_divisor(uint32_t baud, uint32_t base) { + static const unsigned char divfrac[8] = {0, 3, 2, 4, 1, 5, 6, 7}; uint32_t divisor; uint32_t divisor3; @@ -1556,12 +1562,13 @@ static uint32_t ftdi_2232h_baud_base_to_divisor(uint32_t baud, uint32_t base) divisor3 = DIV_ROUND_CLOSEST(8 * base, 10 * baud); divisor = divisor3 >> 3; - divisor |= (uint32_t)divfrac[divisor3 & 0x7] << 14; + divisor |= (uint32_t) divfrac[divisor3 & 0x7] << 14; /* Deal with special cases for highest baud rates. */ - if (divisor == 1) /* 1.0 */ + if (divisor == 1) /* 1.0 */ { divisor = 0; - else if (divisor == 0x4001) /* 1.5 */ + } else if (divisor == 0x4001) /* 1.5 */ { divisor = 1; + } /* * Set this bit to turn off a divide by 2.5 on baud rate generator * This enables baud rates up to 12Mbaud but cannot reach below 1200 @@ -1571,13 +1578,11 @@ static uint32_t ftdi_2232h_baud_base_to_divisor(uint32_t baud, uint32_t base) return divisor; } -static inline uint32_t ftdi_2232h_baud_to_divisor(uint32_t baud) -{ - return ftdi_2232h_baud_base_to_divisor(baud, (uint32_t) 120000000); +static inline uint32_t ftdi_2232h_baud_to_divisor(uint32_t baud) { + return ftdi_2232h_baud_base_to_divisor(baud, (uint32_t) 120000000); } -static inline uint32_t ftdi_get_divisor(cdch_interface_t * p_cdc) -{ +static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { uint32_t baud = p_cdc->requested_line_coding.bit_rate; uint32_t div_value = 0; TU_VERIFY(baud); @@ -1646,13 +1651,13 @@ static inline uint32_t ftdi_get_divisor(cdch_interface_t * p_cdc) return div_value; } -static uint8_t ftdi_get_idx(tuh_xfer_t * xfer) { - uint8_t const channel = (uint8_t) tu_le16toh(xfer->setup->wIndex); // channel index, or 0 for legacy types +static uint8_t ftdi_get_idx(tuh_xfer_t *xfer) { + uint8_t const channel = (uint8_t) tu_le16toh(xfer->setup->wIndex);// channel index, or 0 for legacy types for (uint8_t i = 0; i < CFG_TUH_CDC; i++) { - const cdch_interface_t * p_cdc = &cdch_data[i]; + const cdch_interface_t *p_cdc = &cdch_data[i]; if (p_cdc->daddr == xfer->daddr && (!p_cdc->ftdi.channel || // 0 for legacy types (only interface 0) - channel == p_cdc->ftdi.channel)) { // or multi-channel types (interfaces 0..n) + channel == p_cdc->ftdi.channel)) {// or multi-channel types (interfaces 0..n) return i; } } @@ -1703,29 +1708,28 @@ static bool cp210x_set_request(cdch_interface_t * p_cdc, uint8_t command, uint16 return tuh_control_xfer(&xfer); } -static inline bool cp210x_ifc_enable(cdch_interface_t * p_cdc, uint16_t enabled, +static inline bool cp210x_ifc_enable(cdch_interface_t *p_cdc, uint16_t enabled, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return cp210x_set_request(p_cdc, CP210X_IFC_ENABLE, enabled, NULL, 0, complete_cb, user_data); } -static bool cp210x_set_baudrate_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool cp210x_set_baudrate_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // Not every baud rate is supported. See datasheets and AN205 "CP210x Baud Rate Support" uint32_t baud_le = tu_htole32(p_cdc->requested_line_coding.bit_rate); return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, complete_cb, user_data); } -static bool cp210x_set_line_ctl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool cp210x_set_line_ctl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8, 0); - uint16_t lcr = (uint16_t) ( - (p_cdc->requested_line_coding.data_bits & 0xfUL) << 8 | // data bit quantity is stored in bits 8-11 - (p_cdc->requested_line_coding.parity & 0xfUL) << 4 | // parity is stored in bits 4-7, same coding - (p_cdc->requested_line_coding.stop_bits & 0xfUL)); // parity is stored in bits 0-3, same coding + uint16_t lcr = (uint16_t) ((p_cdc->requested_line_coding.data_bits & 0xfUL) << 8 | // data bit quantity is stored in bits 8-11 + (p_cdc->requested_line_coding.parity & 0xfUL) << 4 | // parity is stored in bits 4-7, same coding + (p_cdc->requested_line_coding.stop_bits & 0xfUL)); // parity is stored in bits 0-3, same coding return cp210x_set_request(p_cdc, CP210X_SET_LINE_CTL, lcr, NULL, 0, complete_cb, user_data); } -static inline bool cp210x_set_mhs(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static inline bool cp210x_set_mhs(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // CP210x has the same bit coding return cp210x_set_request(p_cdc, CP210X_SET_MHS, (uint16_t) (CP210X_CONTROL_WRITE_DTR | CP210X_CONTROL_WRITE_RTS | @@ -1736,16 +1740,16 @@ static inline bool cp210x_set_mhs(cdch_interface_t * p_cdc, tuh_xfer_cb_t comple //------------- Driver API -------------// // internal control complete to update state such as line state, encoding -static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { +static void cp210x_internal_control_complete(tuh_xfer_t *xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); + cdch_interface_t *p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); TU_LOG_P_CDC_BOOL("control complete", success); if (success) { - switch(xfer->setup->bRequest) { + switch (xfer->setup->bRequest) { case CP210X_SET_MHS: p_cdc->line_state = p_cdc->requested_line_state; break; @@ -1770,21 +1774,21 @@ static void cp210x_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool cp210x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool cp210x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(cp210x_set_baudrate_request(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); return true; } -static bool cp210x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool cp210x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(cp210x_set_line_ctl(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); return true; } -static void cp210x_set_line_coding_stage1_complete(tuh_xfer_t * xfer) { +static void cp210x_set_line_coding_stage1_complete(tuh_xfer_t *xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); set_line_coding_stage1_complete(xfer, itf_num, cp210x_set_line_ctl, // control request function to set data format @@ -1792,7 +1796,7 @@ static void cp210x_set_line_coding_stage1_complete(tuh_xfer_t * xfer) { } // 2 stages: set baudrate (stage1) + set data format (stage2) -static bool cp210x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool cp210x_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return set_line_coding_sequence(p_cdc, cp210x_set_baudrate_request, // control request function to set baudrate cp210x_set_line_ctl, // control request function to set data format @@ -1801,7 +1805,7 @@ static bool cp210x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t compl complete_cb, user_data); } -static bool cp210x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool cp210x_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(cp210x_set_mhs(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); @@ -1818,64 +1822,66 @@ enum { CONFIG_CP210X_COMPLETE }; -static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { +static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { // CP210x Interface includes 1 vendor interface + 2 bulk endpoints TU_VERIFY(itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0 && itf_desc->bNumEndpoints == 2); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 2*sizeof(tusb_desc_endpoint_t) <= max_len); + TU_VERIFY(sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t) <= max_len); - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); + cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); p_cdc->serial_drid = SERIAL_DRIVER_CP210X; // endpoint pair - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); // data endpoints expected to be in pairs return open_ep_stream_pair(p_cdc, desc_ep); } -static void cp210x_process_config(tuh_xfer_t * xfer) { - uintptr_t const state = xfer->user_data; - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); +static bool cp210x_process_set_config(tuh_xfer_t *xfer) { + const uint8_t state = (uint8_t) xfer->user_data; + uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS); + TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); switch (state) { case CONFIG_CP210X_IFC_ENABLE: - p_cdc->user_control_cb = cp210x_process_config; // set once for whole process config - TU_ASSERT_COMPLETE(cp210x_ifc_enable(p_cdc, CP210X_UART_ENABLE, cp210x_process_config, - CONFIG_CP210X_SET_BAUDRATE_REQUEST)); + TU_ASSERT(cp210x_ifc_enable(p_cdc, CP210X_UART_ENABLE, cdch_process_set_config, + PROCESS_CONFIG_STATE(idx, CONFIG_CP210X_SET_BAUDRATE_REQUEST))); break; case CONFIG_CP210X_SET_BAUDRATE_REQUEST: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT_COMPLETE(cp210x_set_baudrate_request(p_cdc, cp210x_internal_control_complete, - CONFIG_CP210X_SET_LINE_CTL)); - break; + p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + p_cdc->user_control_cb = cdch_process_set_config; + TU_ASSERT(cp210x_set_baudrate_request(p_cdc, cp210x_internal_control_complete, + PROCESS_CONFIG_STATE(idx, CONFIG_CP210X_SET_LINE_CTL))); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif case CONFIG_CP210X_SET_LINE_CTL: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - TU_ASSERT_COMPLETE(cp210x_set_line_ctl(p_cdc, cp210x_internal_control_complete, - CONFIG_CP210X_SET_DTR_RTS)); - break; + p_cdc->user_control_cb = cdch_process_set_config; + TU_ASSERT(cp210x_set_line_ctl(p_cdc, cp210x_internal_control_complete, + PROCESS_CONFIG_STATE(idx, CONFIG_CP210X_SET_DTR_RTS))); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif case CONFIG_CP210X_SET_DTR_RTS: #ifdef LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; - TU_ASSERT_COMPLETE(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, - CONFIG_CP210X_COMPLETE)); - break; + p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; + p_cdc->user_control_cb = cdch_process_set_config; + TU_ASSERT(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, + PROCESS_CONFIG_STATE(idx, CONFIG_CP210X_COMPLETE))); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif case CONFIG_CP210X_COMPLETE: @@ -1883,9 +1889,10 @@ static void cp210x_process_config(tuh_xfer_t * xfer) { break; default: - TU_ASSERT_COMPLETE(false); - break; + return false; } + + return true; } #endif @@ -1896,13 +1903,13 @@ static void cp210x_process_config(tuh_xfer_t * xfer) { #if CFG_TUH_CDC_CH34X -static uint8_t ch34x_get_lcr(cdch_interface_t * p_cdc); -static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t * p_cdc); +static uint8_t ch34x_get_lcr(cdch_interface_t *p_cdc); +static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t *p_cdc); //------------- Control Request -------------// -static bool ch34x_set_request(cdch_interface_t * p_cdc, uint8_t direction, uint8_t request, - uint16_t value, uint16_t index, uint8_t * buffer, uint16_t length, +static bool ch34x_set_request(cdch_interface_t *p_cdc, uint8_t direction, uint8_t request, + uint16_t value, uint16_t index, uint8_t *buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request_setup = { .bmRequestType_bit = { @@ -1917,7 +1924,7 @@ static bool ch34x_set_request(cdch_interface_t * p_cdc, uint8_t direction, uint8 }; // use usbh enum buf since application variable does not live long enough - uint8_t * enum_buf = NULL; + uint8_t *enum_buf = NULL; if (buffer && length > 0) { enum_buf = usbh_get_enum_buf(); @@ -1938,18 +1945,18 @@ static bool ch34x_set_request(cdch_interface_t * p_cdc, uint8_t direction, uint8 return tuh_control_xfer(&xfer); } -static inline bool ch34x_control_out(cdch_interface_t * p_cdc, uint8_t request, uint16_t value, uint16_t index, +static inline bool ch34x_control_out(cdch_interface_t *p_cdc, uint8_t request, uint16_t value, uint16_t index, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ch34x_set_request(p_cdc, TUSB_DIR_OUT, request, value, index, NULL, 0, complete_cb, user_data); } -static inline bool ch34x_control_in(cdch_interface_t * p_cdc, uint8_t request, uint16_t value, uint16_t index, - uint8_t * buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static inline bool ch34x_control_in(cdch_interface_t *p_cdc, uint8_t request, uint16_t value, uint16_t index, + uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ch34x_set_request(p_cdc, TUSB_DIR_IN, request, value, index, buffer, buffersize, complete_cb, user_data); } -static inline bool ch34x_write_reg(cdch_interface_t * p_cdc, uint16_t reg, uint16_t reg_value, +static inline bool ch34x_write_reg(cdch_interface_t *p_cdc, uint16_t reg, uint16_t reg_value, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, reg, reg_value, complete_cb, user_data); } @@ -1960,36 +1967,33 @@ static inline bool ch34x_write_reg(cdch_interface_t * p_cdc, uint16_t reg, uint1 // return ch34x_control_in ( p_cdc, CH34X_REQ_READ_REG, reg, 0, buffer, buffersize, complete_cb, user_data ); //} -static bool ch34x_write_reg_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ch34x_write_reg_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint8_t const lcr = ch34x_get_lcr(p_cdc); TU_VERIFY(lcr); - return ch34x_write_reg(p_cdc, CH32X_REG16_LCR2_LCR, lcr, complete_cb, user_data); } -static bool ch34x_write_reg_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ch34x_write_reg_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc); TU_VERIFY(div_ps); - return ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, complete_cb, user_data); } -static bool ch34x_modem_ctrl_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t control = ~((p_cdc->requested_line_state.rts ? CH34X_BIT_RTS : 0) | // CH34x signals are inverted +static bool ch34x_modem_ctrl_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint8_t control = ~((p_cdc->requested_line_state.rts ? CH34X_BIT_RTS : 0) |// CH34x signals are inverted (p_cdc->requested_line_state.dtr ? CH34X_BIT_DTR : 0)); - return ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, complete_cb, user_data); } //------------- Driver API -------------// // internal control complete to update state such as line state, encoding -static void ch34x_internal_control_complete(tuh_xfer_t * xfer) { +static void ch34x_internal_control_complete(tuh_xfer_t *xfer) { // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber uint8_t const itf_num = 0; uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); + cdch_interface_t *p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); TU_LOG_P_CDC_BOOL("control complete", success); @@ -2028,21 +2032,21 @@ static void ch34x_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool ch34x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ch34x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(ch34x_write_reg_data_format(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); return true; } -static bool ch34x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool ch34x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); return true; } -static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t * xfer) { +static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t *xfer) { // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber uint8_t const itf_num = 0; set_line_coding_stage1_complete(xfer, itf_num, @@ -2103,20 +2107,19 @@ static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, ui return true; } -static void ch34x_process_config(tuh_xfer_t* xfer) { - uintptr_t const state = xfer->user_data; - // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber - uint8_t const itf_num = 0; +static bool ch34x_process_set_config(tuh_xfer_t *xfer) { + const uint8_t state = (uint8_t) xfer->user_data; + uint8_t const itf_num = 0; // CH34x has only interface 0, since wIndex is used as payload uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT_COMPLETE(p_cdc && xfer->result == XFER_RESULT_SUCCESS); - uint8_t buffer[2]; // TODO remove + cdch_interface_t *p_cdc = get_itf(idx); + uint8_t buffer[2];// TODO remove + + TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); switch (state) { case CONFIG_CH34X_READ_VERSION: - p_cdc->user_control_cb = ch34x_process_config; // set once for whole process config - TU_ASSERT_COMPLETE(ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, - ch34x_process_config, CONFIG_CH34X_SERIAL_INIT)); + TU_ASSERT(ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_CH34X_SERIAL_INIT))); break; case CONFIG_CH34X_SERIAL_INIT: { @@ -2125,39 +2128,39 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { TU_LOG_P_CDC("Chip Version = 0x%02x", version); // only versions >= 0x30 are tested, below 0x30 seems having other programming // see drivers from WCH vendor, Linux kernel and FreeBSD - TU_ASSERT_COMPLETE(version >= 0x30); - // init CH34x with line coding - p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; - uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc); - TU_ASSERT_COMPLETE(div_ps); - uint8_t const lcr = ch34x_get_lcr(p_cdc); - TU_ASSERT_COMPLETE(lcr); - TU_ASSERT_COMPLETE(ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, tu_u16(lcr, 0x9c), div_ps, - ch34x_process_config, CONFIG_CH34X_SPECIAL_REG_WRITE)); + if (version >= 0x30) { + // init CH34x with line coding + p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; + uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc); + uint8_t const lcr = ch34x_get_lcr(p_cdc); + TU_ASSERT(div_ps != 0 && lcr != 0); + TU_ASSERT(ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, tu_u16(lcr, 0x9c), div_ps, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_CH34X_SPECIAL_REG_WRITE))); + } break; } case CONFIG_CH34X_SPECIAL_REG_WRITE: // overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver p_cdc->line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; - TU_ASSERT_COMPLETE(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, - ch34x_process_config, CONFIG_CH34X_FLOW_CONTROL)); + TU_ASSERT(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_CH34X_FLOW_CONTROL))); break; case CONFIG_CH34X_FLOW_CONTROL: // no hardware flow control - TU_ASSERT_COMPLETE(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x27, CH341_REG_0x27), 0x0000, - ch34x_process_config, CONFIG_CH34X_MODEM_CONTROL)); + TU_ASSERT(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x27, CH341_REG_0x27), 0x0000, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_CH34X_MODEM_CONTROL))); break; case CONFIG_CH34X_MODEM_CONTROL: #ifdef LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; - TU_ASSERT_COMPLETE(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, - CONFIG_CH34X_COMPLETE)); - break; + p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; + p_cdc->user_control_cb = cdch_process_set_config; + TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, PROCESS_CONFIG_STATE(idx, CONFIG_CH34X_COMPLETE))); + break; #else - TU_ATTR_FALLTHROUGH; + TU_ATTR_FALLTHROUGH; #endif case CONFIG_CH34X_COMPLETE: @@ -2165,15 +2168,16 @@ static void ch34x_process_config(tuh_xfer_t* xfer) { break; default: - TU_ASSERT_COMPLETE(false); break; } + + return true; } //------------- Helper -------------// // calculate divisor and prescaler for baudrate, return it as 16-bit combined value -static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t * p_cdc) { +static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t *p_cdc) { uint32_t const baval = p_cdc->requested_line_coding.bit_rate; uint8_t a; uint8_t b; @@ -2219,20 +2223,20 @@ static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t * p_cdc) { // reg divisor = a, reg prescaler = b // According to linux code we need to set bit 7 of UCHCOM_REG_BPS_PRE, // otherwise the chip will buffer data. - return (uint16_t) ((uint16_t)a << 8 | 0x80 | b); + return (uint16_t) ((uint16_t) a << 8 | 0x80 | b); } // calculate lcr value from data coding -static uint8_t ch34x_get_lcr(cdch_interface_t * p_cdc) { +static uint8_t ch34x_get_lcr(cdch_interface_t *p_cdc) { uint8_t const stop_bits = p_cdc->requested_line_coding.stop_bits; - uint8_t const parity = p_cdc->requested_line_coding.parity; + uint8_t const parity = p_cdc->requested_line_coding.parity; uint8_t const data_bits = p_cdc->requested_line_coding.data_bits; uint8_t lcr = CH34X_LCR_ENABLE_RX | CH34X_LCR_ENABLE_TX; TU_VERIFY(data_bits >= 5 && data_bits <= 8); lcr |= (uint8_t) (data_bits - 5); - switch(parity) { + switch (parity) { case CDC_LINE_CODING_PARITY_NONE: break; @@ -2271,14 +2275,13 @@ static uint8_t ch34x_get_lcr(cdch_interface_t * p_cdc) { //--------------------------------------------------------------------+ #if CFG_TUH_CDC_PL2303 -static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t step, +static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool pl2303_encode_baud_rate(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]); +static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]); //------------- Control Request -------------// - -static bool pl2303_set_request(cdch_interface_t * p_cdc, uint8_t request, uint8_t requesttype, - uint16_t value, uint16_t index, uint8_t * buffer, uint16_t length, +static bool pl2303_set_request(cdch_interface_t *p_cdc, uint8_t request, uint8_t requesttype, + uint16_t value, uint16_t index, uint8_t *buffer, uint16_t length, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request_setup = { .bmRequestType = requesttype, @@ -2289,7 +2292,7 @@ static bool pl2303_set_request(cdch_interface_t * p_cdc, uint8_t request, uint8_ }; // use usbh enum buf since application variable does not live long enough - uint8_t * enum_buf = NULL; + uint8_t *enum_buf = NULL; if (buffer && length > 0) { enum_buf = usbh_get_enum_buf(); @@ -2310,34 +2313,28 @@ static bool pl2303_set_request(cdch_interface_t * p_cdc, uint8_t request, uint8_ return tuh_control_xfer(&xfer); } -static bool pl2303_vendor_read(cdch_interface_t * p_cdc, uint16_t value, uint8_t * buf, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN] ? - PL2303_VENDOR_READ_NREQUEST : PL2303_VENDOR_READ_REQUEST; +static bool pl2303_vendor_read(cdch_interface_t *p_cdc, uint16_t value, uint8_t *buf, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN] ? PL2303_VENDOR_READ_NREQUEST : PL2303_VENDOR_READ_REQUEST; return pl2303_set_request(p_cdc, request, PL2303_VENDOR_READ_REQUEST_TYPE, value, 0, buf, 1, complete_cb, user_data); } -static bool pl2303_vendor_write(cdch_interface_t * p_cdc, uint16_t value, uint16_t index, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN] ? - PL2303_VENDOR_WRITE_NREQUEST : PL2303_VENDOR_WRITE_REQUEST; +static bool pl2303_vendor_write(cdch_interface_t *p_cdc, uint16_t value, uint16_t index, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN] ? PL2303_VENDOR_WRITE_NREQUEST : PL2303_VENDOR_WRITE_REQUEST; return pl2303_set_request(p_cdc, request, PL2303_VENDOR_WRITE_REQUEST_TYPE, value, index, NULL, 0, complete_cb, user_data); } -static inline bool pl2303_supports_hx_status(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +static inline bool pl2303_supports_hx_status(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint8_t buf = 0; return pl2303_set_request(p_cdc, PL2303_VENDOR_READ_REQUEST, PL2303_VENDOR_READ_REQUEST_TYPE, PL2303_READ_TYPE_HX_STATUS, 0, &buf, 1, complete_cb, user_data); } -static inline bool pl2303_set_control_lines(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +static inline bool pl2303_set_control_lines(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // PL2303 has the same bit coding return pl2303_set_request(p_cdc, PL2303_SET_CONTROL_REQUEST, PL2303_SET_CONTROL_REQUEST_TYPE, p_cdc->requested_line_state.all, 0, NULL, 0, complete_cb, user_data); @@ -2348,7 +2345,7 @@ static inline bool pl2303_set_control_lines(cdch_interface_t * p_cdc, tuh_xfer_c // return pl2303_set_request(p_cdc, PL2303_GET_LINE_REQUEST, PL2303_GET_LINE_REQUEST_TYPE, 0, 0, buf, PL2303_LINE_CODING_BUFSIZE); //} -static bool pl2303_set_line_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool pl2303_set_line_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // the caller has to precheck, that the new line coding different than the current, else false returned uint8_t buf[PL2303_LINE_CODING_BUFSIZE]; /* @@ -2390,8 +2387,7 @@ static bool pl2303_set_line_request(cdch_interface_t * p_cdc, tuh_xfer_cb_t comp // return pl2303_set_request(p_cdc, PL2303_BREAK_REQUEST, PL2303_BREAK_REQUEST_TYPE, state, 0, NULL, 0); //} -static inline int pl2303_clear_halt(cdch_interface_t * p_cdc, uint8_t endp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ +static inline int pl2303_clear_halt(cdch_interface_t *p_cdc, uint8_t endp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { /* we don't care if it wasn't halted first. in fact some devices * (like some ibmcam model 1 units) seem to expect hosts to make * this request for iso endpoints, which can't halt! @@ -2403,22 +2399,22 @@ static inline int pl2303_clear_halt(cdch_interface_t * p_cdc, uint8_t endp, tuh_ //------------- Driver API -------------// // internal control complete to update state such as line state, encoding -static void pl2303_internal_control_complete(tuh_xfer_t * xfer) { +static void pl2303_internal_control_complete(tuh_xfer_t *xfer) { // PL2303 has only interface 0, because wIndex is used as payload and not for bInterfaceNumber uint8_t const itf_num = 0; uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); + cdch_interface_t *p_cdc = get_itf(idx); + TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); TU_LOG_P_CDC_BOOL("control complete", success); if (success) { if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && - xfer->setup->bmRequestType == PL2303_SET_LINE_REQUEST_TYPE) { + xfer->setup->bmRequestType == PL2303_SET_LINE_REQUEST_TYPE) { p_cdc->line_coding = p_cdc->requested_line_coding; } if (xfer->setup->bRequest == PL2303_SET_CONTROL_REQUEST && - xfer->setup->bmRequestType == PL2303_SET_CONTROL_REQUEST_TYPE) { + xfer->setup->bmRequestType == PL2303_SET_CONTROL_REQUEST_TYPE) { p_cdc->line_state = p_cdc->requested_line_state; } } @@ -2429,14 +2425,14 @@ static void pl2303_internal_control_complete(tuh_xfer_t * xfer) { } } -static bool pl2303_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool pl2303_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); return true; } -static bool pl2303_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool pl2303_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->requested_line_coding.bit_rate = p_cdc->line_coding.bit_rate; p_cdc->user_control_cb = complete_cb; TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); @@ -2444,7 +2440,7 @@ static bool pl2303_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t compl return true; } -static bool pl2303_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool pl2303_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->requested_line_coding.stop_bits = p_cdc->line_coding.stop_bits; p_cdc->requested_line_coding.parity = p_cdc->line_coding.parity; p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits; @@ -2454,7 +2450,7 @@ static bool pl2303_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete return true; } -static bool pl2303_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static bool pl2303_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // PL2303 has the same bit coding p_cdc->user_control_cb = complete_cb; TU_ASSERT(pl2303_set_control_lines(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); @@ -2487,19 +2483,19 @@ enum { CONFIG_PL2303_COMPLETE }; -static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { +static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { // PL2303 Interface includes 1 vendor interface + 1 interrupt endpoints + 2 bulk TU_VERIFY(itf_desc->bNumEndpoints == 3); TU_VERIFY(sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t) <= max_len); - cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); + cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); TU_VERIFY(p_cdc); p_cdc->serial_drid = SERIAL_DRIVER_PL2303; p_cdc->pl2303.serial_private.quirks = 0; p_cdc->pl2303.supports_hx_status = false; - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const * ) tu_desc_next(itf_desc); + tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); // Interrupt endpoint: not used for now TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && @@ -2514,158 +2510,167 @@ static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, u return true; } -static void pl2303_process_config(tuh_xfer_t * xfer) { - uintptr_t const state = xfer->user_data; +static bool pl2303_process_set_config(tuh_xfer_t *xfer) { + const uint8_t state = (uint8_t) xfer->user_data; // PL2303 has only interface 0, because wIndex is used as payload and not for bInterfaceNumber uint8_t const itf_num = 0; uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); + cdch_interface_t *p_cdc = get_itf(idx); // state CONFIG_PL2303_READ1 may have no success due to expected stall by pl2303_supports_hx_status() - TU_ASSERT_COMPLETE(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || xfer->user_data == CONFIG_PL2303_READ1)); uint8_t buf = 0; int8_t type; + TU_ASSERT(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || xfer->user_data == CONFIG_PL2303_READ1)); switch (state) { - // from here sequence overtaken from Linux Kernel function pl2303_startup() case CONFIG_PL2303_GET_DESC: - p_cdc->user_control_cb = pl2303_process_config; // set once for whole process config + p_cdc->user_control_cb = cdch_process_set_config;// set once for whole process config // get device descriptor - TU_ASSERT_COMPLETE(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), - pl2303_process_config, CONFIG_PL2303_DETECT_TYPE)); + TU_ASSERT(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_DETECT_TYPE))); break; case CONFIG_PL2303_DETECT_TYPE: // get type and quirks (step 1) - type = pl2303_detect_type (p_cdc, 1, pl2303_process_config, CONFIG_PL2303_READ1); // step 1 - TU_ASSERT_COMPLETE(type!=PL2303_DETECT_TYPE_FAILED); + type = pl2303_detect_type(p_cdc, 1, cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ1)); + TU_ASSERT(type != PL2303_DETECT_TYPE_FAILED); if (type == PL2303_SUPPORTS_HX_STATUS_TRIGGERED) { break; - } // else: no transfer triggered and continue with CONFIG_PL2303_READ1 + }// else: no transfer triggered and continue with CONFIG_PL2303_READ1 TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_READ1: // get supports_hx_status, type and quirks (step 2), do special read - p_cdc->pl2303.supports_hx_status = ( // will not be true, if coming directly from previous case - xfer->user_data == CONFIG_PL2303_READ1 && xfer->result == XFER_RESULT_SUCCESS ); - type = pl2303_detect_type (p_cdc, 2, NULL, 0); // step 2 now with supports_hx_status - TU_ASSERT_COMPLETE(type!=PL2303_DETECT_TYPE_FAILED); + p_cdc->pl2303.supports_hx_status = (// will not be true, if coming directly from previous case + xfer->user_data == CONFIG_PL2303_READ1 && xfer->result == XFER_RESULT_SUCCESS); + type = pl2303_detect_type(p_cdc, 2, NULL, 0); // step 2 now with supports_hx_status + TU_ASSERT(type != PL2303_DETECT_TYPE_FAILED); p_cdc->pl2303.serial_private.type = &pl2303_type_data[type]; p_cdc->pl2303.serial_private.quirks |= p_cdc->pl2303.serial_private.type->quirks; - #if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL && 0 // can be activated if necessary - TU_LOG_P_CDC("bDeviceClass = 0x%02x bMaxPacketSize0 = %u bcdUSB = 0x%04x bcdDevice = 0x%04x", - desc_dev->bDeviceClass, desc_dev->bMaxPacketSize0, - desc_dev->bcdUSB, desc_dev->bcdDevice ); - uint16_t vid, pid; - TU_ASSERT_COMPLETE(tuh_vid_pid_get(p_cdc->daddr, &vid, &pid)); - TU_LOG_P_CDC("vid = 0x%04x pid = 0x%04x supports_hx_status = %u type = %s quirks = %u", - vid, pid, p_cdc->pl2303.supports_hx_status, - p_cdc->pl2303.serial_private.type->name, p_cdc->pl2303.serial_private.quirks); + #if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL && 0// can be activated if necessary + TU_LOG_P_CDC("bDeviceClass = 0x%02x bMaxPacketSize0 = %u bcdUSB = 0x%04x bcdDevice = 0x%04x", + desc_dev->bDeviceClass, desc_dev->bMaxPacketSize0, + desc_dev->bcdUSB, desc_dev->bcdDevice); + uint16_t vid, pid; + TU_ASSERT(tuh_vid_pid_get(p_cdc->daddr, &vid, &pid)); + TU_LOG_P_CDC("vid = 0x%04x pid = 0x%04x supports_hx_status = %u type = %s quirks = %u", + vid, pid, p_cdc->pl2303.supports_hx_status, + p_cdc->pl2303.serial_private.type->name, p_cdc->pl2303.serial_private.quirks); #endif // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8484, &buf, pl2303_process_config, CONFIG_PL2303_WRITE1)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_WRITE1))); break; - } // else: continue with next step + }// else: continue with next step TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_WRITE1: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 0x0404, 0, pl2303_process_config, CONFIG_PL2303_READ2)); + TU_ASSERT(pl2303_vendor_write(p_cdc, 0x0404, 0, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ2))); break; - } // else: continue with next step + }// else: continue with next step TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_READ2: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8484, &buf, pl2303_process_config, CONFIG_PL2303_READ3)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ3))); break; - } // else: continue with next step + }// else: continue with next step TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_READ3: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8383, &buf, pl2303_process_config, CONFIG_PL2303_READ4)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ4))); break; - } // else: continue with next step + }// else: continue with next step TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_READ4: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8484, &buf, pl2303_process_config, CONFIG_PL2303_WRITE2)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_WRITE2))); break; - } // else: continue with next step + }// else: continue with next step TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_WRITE2: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 0x0404, 1, pl2303_process_config, CONFIG_PL2303_READ5)); + TU_ASSERT(pl2303_vendor_write(p_cdc, 0x0404, 1, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ5))); break; - } // else: continue with next step + }// else: continue with next step TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_READ5: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8484, &buf, pl2303_process_config, CONFIG_PL2303_READ6)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ6))); break; - } // else: continue with next step + }// else: continue with next step TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_READ6: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0x8383, &buf, pl2303_process_config, CONFIG_PL2303_WRITE3)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_WRITE3))); break; - } // else: continue with next step + }// else: continue with next step TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_WRITE3: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 0, 1, pl2303_process_config, CONFIG_PL2303_WRITE4)); + TU_ASSERT(pl2303_vendor_write(p_cdc, 0, 1, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_WRITE4))); break; - } // else: continue with next step + }// else: continue with next step TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_WRITE4: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 1, 0, pl2303_process_config, CONFIG_PL2303_WRITE5)); + TU_ASSERT(pl2303_vendor_write(p_cdc, 1, 0, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_WRITE5))); break; - } // else: continue with next step + }// else: continue with next step TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_WRITE5: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - if (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) { - TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 2, 0x24, pl2303_process_config, CONFIG_PL2303_RESET_ENDP1)); - } else { - TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 2, 0x44, pl2303_process_config, CONFIG_PL2303_RESET_ENDP1)); - } + uint16_t const windex = (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) ? 0x24 : 0x44; + TU_ASSERT(pl2303_vendor_write(p_cdc, 2, windex, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_RESET_ENDP1))); break; - } // else: continue with next step + }// else: continue with next step TU_ATTR_FALLTHROUGH; - // from here sequence overtaken from Linux Kernel function pl2303_open() + // from here sequence overtaken from Linux Kernel function pl2303_open() case CONFIG_PL2303_RESET_ENDP1: // step 1 if (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) { - TU_ASSERT_COMPLETE(pl2303_clear_halt(p_cdc, PL2303_OUT_EP, pl2303_process_config, CONFIG_PL2303_RESET_ENDP2)); + TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_OUT_EP, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_RESET_ENDP2))); } else { /* reset upstream data pipes */ if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, PL2303_HXN_RESET_REG, // skip CONFIG_PL2303_RESET_ENDP2, no 2nd step + TU_ASSERT(pl2303_vendor_write(p_cdc, PL2303_HXN_RESET_REG,// skip CONFIG_PL2303_RESET_ENDP2, no 2nd step PL2303_HXN_RESET_UPSTREAM_PIPE | PL2303_HXN_RESET_DOWNSTREAM_PIPE, - pl2303_process_config, CONFIG_PL2303_LINE_CODING)); + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_LINE_CODING))); } else { - pl2303_vendor_write(p_cdc, 8, 0, pl2303_process_config, CONFIG_PL2303_RESET_ENDP2); + pl2303_vendor_write(p_cdc, 8, 0, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_RESET_ENDP2)); } } break; @@ -2673,91 +2678,96 @@ static void pl2303_process_config(tuh_xfer_t * xfer) { case CONFIG_PL2303_RESET_ENDP2: // step 2 if (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) { - TU_ASSERT_COMPLETE(pl2303_clear_halt(p_cdc, PL2303_IN_EP, pl2303_process_config, CONFIG_PL2303_LINE_CODING)); + TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_IN_EP, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_LINE_CODING))); } else { /* reset upstream data pipes */ if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { // here nothing to do, only structure of previous step overtaken for better reading and comparison } else { - TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 9, 0, pl2303_process_config, CONFIG_PL2303_LINE_CODING)); + TU_ASSERT(pl2303_vendor_write(p_cdc, 9, 0, + cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_LINE_CODING))); } } break; - // from here sequence overtaken from Linux Kernel function pl2303_set_termios() - // unnecessary pl2303_get_line_request() is skipped due to a stall + // from here sequence overtaken from Linux Kernel function pl2303_set_termios() + // unnecessary pl2303_get_line_request() is skipped due to a stall case CONFIG_PL2303_LINE_CODING: - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT_COMPLETE( pl2303_set_line_request(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_MODEM_CONTROL)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + TU_ASSERT(pl2303_set_line_request(p_cdc, pl2303_internal_control_complete, + PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_MODEM_CONTROL))); + break; + #else + TU_ATTR_FALLTHROUGH; + #endif case CONFIG_PL2303_MODEM_CONTROL: - #ifdef LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; - TU_ASSERT_COMPLETE(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_COMPLETE)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif + #ifdef LINE_CONTROL_ON_ENUM + p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; + TU_ASSERT(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, + PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_COMPLETE))); + break; + #else + TU_ATTR_FALLTHROUGH; + #endif -// skipped, because it's not working with each PL230x. flow control can be also set by PL2303 EEPROM Writer Program -// case CONFIG_PL2303_FLOW_CTRL_READ: -// // read flow control register for modify & write back in next step -// if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { -// TU_LOG_P_CDC ( "1\r\n" ); -// TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, PL2303_HXN_FLOWCTRL_REG, &buf, pl2303_process_config, -// CONFIG_PL2303_FLOW_CTRL_WRITE)); -// } else { -// TU_LOG_P_CDC ( "2\r\n" ); -// TU_ASSERT_COMPLETE(pl2303_vendor_read(p_cdc, 0, &buf, pl2303_process_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); -// } -// break; -// -// case CONFIG_PL2303_FLOW_CTRL_WRITE: -// // no flow control -// buf = xfer->buffer[0]; -// if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { -// buf &= (uint8_t) ~PL2303_HXN_FLOWCTRL_MASK; -// buf |= PL2303_HXN_FLOWCTRL_NONE; -// TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, PL2303_HXN_FLOWCTRL_REG, buf, pl2303_process_config, -// CONFIG_PL2303_COMPLETE)); -// } else { -// buf &= (uint8_t) ~PL2303_FLOWCTRL_MASK; -// TU_ASSERT_COMPLETE(pl2303_vendor_write(p_cdc, 0, buf, pl2303_process_config, CONFIG_PL2303_COMPLETE)); -// } -// break; + // skipped, because it's not working with each PL230x. flow control can be also set by PL2303 EEPROM Writer Program + // case CONFIG_PL2303_FLOW_CTRL_READ: + // // read flow control register for modify & write back in next step + // if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { + // TU_LOG_P_CDC ( "1\r\n" ); + // TU_ASSERT(pl2303_vendor_read(p_cdc, PL2303_HXN_FLOWCTRL_REG, &buf, + // cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_FLOW_CTRL_WRITE))); + // } else { + // TU_LOG_P_CDC ( "2\r\n" ); + // TU_ASSERT(pl2303_vendor_read(p_cdc, 0, &buf, cdch_process_set_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); + // } + // break; + // + // case CONFIG_PL2303_FLOW_CTRL_WRITE: + // // no flow control + // buf = xfer->buffer[0]; + // if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { + // buf &= (uint8_t) ~PL2303_HXN_FLOWCTRL_MASK; + // buf |= PL2303_HXN_FLOWCTRL_NONE; + // TU_ASSERT(pl2303_vendor_write(p_cdc, PL2303_HXN_FLOWCTRL_REG, buf, + // cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_COMPLETE))); + // } else { + // buf &= (uint8_t) ~PL2303_FLOWCTRL_MASK; + // TU_ASSERT(pl2303_vendor_write(p_cdc, 0, buf, + // cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_COMPLETE))); + // } + // break; case CONFIG_PL2303_COMPLETE: set_config_complete(idx, 0, true); break; default: - TU_ASSERT_COMPLETE(false); - break; + return false; } + + return true; } //------------- Helper -------------// -static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t step, - tuh_xfer_cb_t complete_cb, uintptr_t user_data ) -{ +static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { /* * Legacy PL2303H, variants 0 and 1 (difference unknown). */ if (desc_dev->bDeviceClass == 0x02) { - return TYPE_H; /* variant 0 */ + return TYPE_H; /* variant 0 */ } if (desc_dev->bMaxPacketSize0 != 0x40) { if (desc_dev->bDeviceClass == 0x00 || desc_dev->bDeviceClass == 0xff) { - return TYPE_H; /* variant 1 */ + return TYPE_H; /* variant 1 */ } - return TYPE_H; /* variant 0 */ + return TYPE_H; /* variant 0 */ } switch (desc_dev->bcdUSB) { @@ -2782,7 +2792,7 @@ static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t step, case 0x300: /* GT / TA */ if (step == 1) { // step 1 trigger pl2303_supports_hx_status() request - TU_ASSERT(pl2303_supports_hx_status (p_cdc, complete_cb, user_data), PL2303_DETECT_TYPE_FAILED); + TU_ASSERT(pl2303_supports_hx_status(p_cdc, complete_cb, user_data), PL2303_DETECT_TYPE_FAILED); return PL2303_SUPPORTS_HX_STATUS_TRIGGERED; } else { // step 2 use supports_hx_status @@ -2798,7 +2808,7 @@ static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t step, case 0x500: /* GE / TB */ if (step == 1) { // step 1 trigger pl2303_supports_hx_status() request - TU_ASSERT(pl2303_supports_hx_status (p_cdc, complete_cb, user_data), PL2303_DETECT_TYPE_FAILED); + TU_ASSERT(pl2303_supports_hx_status(p_cdc, complete_cb, user_data), PL2303_DETECT_TYPE_FAILED); return PL2303_SUPPORTS_HX_STATUS_TRIGGERED; } else { // step 2 use supports_hx_status @@ -2829,8 +2839,7 @@ static int8_t pl2303_detect_type(cdch_interface_t * p_cdc, uint8_t step, * Returns the nearest supported baud rate that can be set directly without * using divisors. */ -static uint32_t pl2303_get_supported_baud_rate(uint32_t baud) -{ +static uint32_t pl2303_get_supported_baud_rate(uint32_t baud) { static const uint32_t baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600, 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800, @@ -2859,8 +2868,7 @@ static uint32_t pl2303_get_supported_baud_rate(uint32_t baud) * NOTE: If unsupported baud rates are set directly, the PL2303 seems to * use 9600 baud. */ -static uint32_t pl2303_encode_baud_rate_direct(uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE], uint32_t baud) -{ +static uint32_t pl2303_encode_baud_rate_direct(uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE], uint32_t baud) { uint32_t baud_le = tu_htole32(baud); buf[0] = (uint8_t) ( baud_le & 0xff); buf[1] = (uint8_t) ((baud_le >> 8) & 0xff); @@ -2870,8 +2878,7 @@ static uint32_t pl2303_encode_baud_rate_direct(uint8_t buf[PL2303_LINE_CODING_BA return baud; } -static uint32_t pl2303_encode_baud_rate_divisor(uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE], uint32_t baud) -{ +static uint32_t pl2303_encode_baud_rate_divisor(uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE], uint32_t baud) { uint32_t baseline, mantissa, exponent; /* @@ -2899,7 +2906,7 @@ static uint32_t pl2303_encode_baud_rate_divisor(uint8_t buf[PL2303_LINE_CODING_B buf[3] = 0x80; buf[2] = 0; - buf[1] = (uint8_t) ((exponent << 1 | mantissa >> 8) & 0xff); + buf[1] = (uint8_t) ((exponent << 1 | mantissa >> 8) & 0xff); buf[0] = (uint8_t) (mantissa & 0xff); /* Calculate and return the exact baud rate. */ @@ -2908,8 +2915,7 @@ static uint32_t pl2303_encode_baud_rate_divisor(uint8_t buf[PL2303_LINE_CODING_B return baud; } -static uint32_t pl2303_encode_baud_rate_divisor_alt(uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE], uint32_t baud) -{ +static uint32_t pl2303_encode_baud_rate_divisor_alt(uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE], uint32_t baud) { uint32_t baseline, mantissa, exponent; /* @@ -2922,7 +2928,7 @@ static uint32_t pl2303_encode_baud_rate_divisor_alt(uint8_t buf[PL2303_LINE_CODI baseline = 12000000 * 32; mantissa = baseline / baud; if (mantissa == 0) { - mantissa = 1; /* Avoid dividing by zero if baud > 32 * 12M. */ + mantissa = 1; /* Avoid dividing by zero if baud > 32 * 12M. */ } exponent = 0; while (mantissa >= 2048) { @@ -2938,7 +2944,7 @@ static uint32_t pl2303_encode_baud_rate_divisor_alt(uint8_t buf[PL2303_LINE_CODI buf[3] = 0x80; buf[2] = (uint8_t) (exponent & 0x01); - buf[1] = (uint8_t) (((exponent & (uint32_t) ~0x01) << 4 | mantissa >> 8 ) & 0xff); + buf[1] = (uint8_t) (((exponent & (uint32_t) ~0x01) << 4 | mantissa >> 8) & 0xff); buf[0] = (uint8_t) (mantissa & 0xff); /* Calculate and return the exact baud rate. */ @@ -2947,8 +2953,7 @@ static uint32_t pl2303_encode_baud_rate_divisor_alt(uint8_t buf[PL2303_LINE_CODI return baud; } -static bool pl2303_encode_baud_rate(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]) -{ +static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]) { uint32_t baud = p_cdc->requested_line_coding.bit_rate; uint32_t baud_sup; From 506edc626709ca92dd9c38d6c6f5813f30a27692 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 18 Jun 2025 18:55:31 +0700 Subject: [PATCH 229/382] add get_itf_by_xfer() to better determine cdc interface from xfer complete callback --- src/class/cdc/cdc_host.c | 182 ++++++++++++++++++++++----------------- 1 file changed, 105 insertions(+), 77 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index b6e9cb297..3be61e654 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -131,9 +131,6 @@ CFG_TUH_MEM_SECTION static cdch_epbuf_t cdch_epbuf[CFG_TUH_CDC]; // Serial Driver //--------------------------------------------------------------------+ -// for process_set_config user_data: idx (byte1) and state (byte0) -#define PROCESS_CONFIG_STATE(_idx, _state) tu_u16(_idx, _state) - static void cdch_process_set_config(tuh_xfer_t *xfer); //------------- ACM prototypes -------------// @@ -327,13 +324,16 @@ TU_VERIFY_STATIC(TU_ARRAY_SIZE(serial_drivers) == SERIAL_DRIVER_COUNT, "Serial d // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -static inline cdch_interface_t * get_itf(uint8_t idx) { +TU_ATTR_ALWAYS_INLINE static inline cdch_interface_t * get_itf(uint8_t idx) { TU_ASSERT(idx < CFG_TUH_CDC, NULL); cdch_interface_t * p_cdc = &cdch_data[idx]; - return (p_cdc->daddr != 0) ? p_cdc : NULL; } +TU_ATTR_ALWAYS_INLINE static inline uint8_t get_idx_by_ptr(cdch_interface_t* p_cdc) { + return p_cdc - cdch_data; +} + static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) { for(uint8_t i=0; idaddr != 0, NULL); + for(uint8_t i=0; idaddr == xfer->daddr) { + switch (p_cdc->serial_drid) { + #if CFG_TUH_CDC_CP210X + case SERIAL_DRIVER_CP210X: + #endif + case SERIAL_DRIVER_ACM: { + // Driver use wIndex for bInterfaceNumber + const uint8_t itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + if (p_cdc->bInterfaceNumber == itf_num) { + return p_cdc; + } + break; + } + + #if CFG_TUH_CDC_FTDI + case SERIAL_DRIVER_FTDI: { + // FTDI uses wIndex for channel number, if channel is 0 then it is the default channel + const uint8_t channel = (uint8_t) tu_le16toh(xfer->setup->wIndex); + if (p_cdc->ftdi.channel == 0 || p_cdc->ftdi.channel == channel) { + return p_cdc; + } + break; + } + #endif + + #if CFG_TUH_CDC_CH34X + case SERIAL_DRIVER_CH34X: + // ch34x has only one interface + return p_cdc; + #endif + + #if CFG_TUH_CDC_PL2303 + case SERIAL_DRIVER_PL2303: + // pl2303 has only one interface + return p_cdc; + #endif + + default: + break; + } + } + } + + return NULL; +} + static cdch_interface_t * make_new_itf(uint8_t daddr, tusb_desc_interface_t const * itf_desc) { for(uint8_t i=0; iserial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set control line state dtr = %u rts = %u", line_state.dtr, line_state.rts ); + TU_LOG_P_CDC("set control line state dtr = %u rts = %u", line_state.dtr, line_state.rts); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line_state = line_state; @@ -614,8 +665,6 @@ bool tuh_cdc_set_control_line_state_u(uint8_t idx, cdc_line_control_state_t line if (ret && !complete_cb) { p_cdc->line_state = line_state; } -// TU_LOG_P_CDC_BOOL("set control line state", ret); - return ret; } @@ -893,9 +942,9 @@ static void set_config_complete(uint8_t idx, uint8_t itf_offset, bool success) { } static void cdch_process_set_config(tuh_xfer_t *xfer) { - const uint8_t idx = tu_u32_byte1(xfer->user_data); - cdch_interface_t *p_cdc = get_itf(idx); + cdch_interface_t *p_cdc = get_itf_by_xfer(xfer); TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); + const uint8_t idx = get_idx_by_ptr(p_cdc); if (!serial_drivers[p_cdc->serial_drid].process_set_config(xfer)) { const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; @@ -916,7 +965,7 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { xfer.daddr = daddr; xfer.result = XFER_RESULT_SUCCESS; xfer.setup = &request; - xfer.user_data = PROCESS_CONFIG_STATE(idx, 0); // initial state 0 + xfer.user_data = 0; // initial state 0 cdch_process_set_config(&xfer); return true; @@ -1093,7 +1142,7 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint1 } static bool acm_process_set_config(tuh_xfer_t *xfer) { - const uint8_t state = (uint8_t) xfer->user_data; + const uintptr_t state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t *p_cdc = get_itf(idx); @@ -1104,7 +1153,7 @@ static bool acm_process_set_config(tuh_xfer_t *xfer) { #ifdef LINE_CONTROL_ON_ENUM if (p_cdc->acm_capability.support_line_request) { p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; - TU_ASSERT(acm_set_control_line_state(p_cdc, cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_ACM_SET_LINE_CODING))); + TU_ASSERT(acm_set_control_line_state(p_cdc, cdch_process_set_config, CONFIG_ACM_SET_LINE_CODING)); break; } #endif @@ -1114,7 +1163,7 @@ static bool acm_process_set_config(tuh_xfer_t *xfer) { #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM if (p_cdc->acm_capability.support_line_request) { p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(acm_set_line_coding(p_cdc, cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_ACM_COMPLETE))); + TU_ASSERT(acm_set_line_coding(p_cdc, cdch_process_set_config, CONFIG_ACM_COMPLETE)); break; } #endif @@ -1326,7 +1375,7 @@ static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint } static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { - const uint8_t state = (uint8_t) xfer->user_data; + const uintptr_t state = xfer->user_data; uint8_t const idx = ftdi_get_idx(xfer); cdch_interface_t *p_cdc = get_itf(idx); uint8_t const itf_num = p_cdc->bInterfaceNumber; @@ -1338,7 +1387,7 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { // get device descriptor if (itf_num == 0) { // only necessary for 1st interface. other interface overtake type from interface 0 TU_ASSERT(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_DETERMINE_TYPE))); + cdch_process_set_config, CONFIG_FTDI_DETERMINE_TYPE)); break; } TU_ATTR_FALLTHROUGH; @@ -1370,7 +1419,7 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { // from here sequence overtaken from Linux Kernel function ftdi_open() case CONFIG_FTDI_SIO_RESET: p_cdc->user_control_cb = cdch_process_set_config; - TU_ASSERT(ftdi_sio_reset(p_cdc, cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_SET_DATA))); + TU_ASSERT(ftdi_sio_reset(p_cdc, cdch_process_set_config, CONFIG_FTDI_SET_DATA)); break; // from here sequence overtaken from Linux Kernel function ftdi_set_termios() @@ -1378,7 +1427,7 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; p_cdc->user_control_cb = cdch_process_set_config; - TU_ASSERT(ftdi_set_data_request(p_cdc, ftdi_internal_control_complete, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_SET_BAUDRATE))); + TU_ASSERT(ftdi_set_data_request(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_SET_BAUDRATE)); break; #else TU_ATTR_FALLTHROUGH; @@ -1387,7 +1436,7 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { case CONFIG_FTDI_SET_BAUDRATE: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->user_control_cb = cdch_process_set_config; - TU_ASSERT(ftdi_change_speed(p_cdc, ftdi_internal_control_complete, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_FLOW_CONTROL))); + TU_ASSERT(ftdi_change_speed(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_FLOW_CONTROL)); break; #else TU_ATTR_FALLTHROUGH; @@ -1396,14 +1445,14 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { case CONFIG_FTDI_FLOW_CONTROL: // disable flow control TU_ASSERT(ftdi_set_request(p_cdc, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, FTDI_SIO_DISABLE_FLOW_CTRL, - p_cdc->ftdi.channel, cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_MODEM_CTRL))); + p_cdc->ftdi.channel, cdch_process_set_config, CONFIG_FTDI_MODEM_CTRL)); break; case CONFIG_FTDI_MODEM_CTRL: #ifdef LINE_CONTROL_ON_ENUM p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; p_cdc->user_control_cb = cdch_process_set_config; - TU_ASSERT(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, PROCESS_CONFIG_STATE(idx, CONFIG_FTDI_COMPLETE))); + TU_ASSERT(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; @@ -1840,7 +1889,7 @@ static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui } static bool cp210x_process_set_config(tuh_xfer_t *xfer) { - const uint8_t state = (uint8_t) xfer->user_data; + const uintptr_t state = xfer->user_data; uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t *p_cdc = get_itf(idx); @@ -1848,16 +1897,14 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) { switch (state) { case CONFIG_CP210X_IFC_ENABLE: - TU_ASSERT(cp210x_ifc_enable(p_cdc, CP210X_UART_ENABLE, cdch_process_set_config, - PROCESS_CONFIG_STATE(idx, CONFIG_CP210X_SET_BAUDRATE_REQUEST))); + TU_ASSERT(cp210x_ifc_enable(p_cdc, CP210X_UART_ENABLE, cdch_process_set_config, CONFIG_CP210X_SET_BAUDRATE_REQUEST)); break; case CONFIG_CP210X_SET_BAUDRATE_REQUEST: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; p_cdc->user_control_cb = cdch_process_set_config; - TU_ASSERT(cp210x_set_baudrate_request(p_cdc, cp210x_internal_control_complete, - PROCESS_CONFIG_STATE(idx, CONFIG_CP210X_SET_LINE_CTL))); + TU_ASSERT(cp210x_set_baudrate_request(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_SET_LINE_CTL)); break; #else TU_ATTR_FALLTHROUGH; @@ -1866,8 +1913,7 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) { case CONFIG_CP210X_SET_LINE_CTL: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->user_control_cb = cdch_process_set_config; - TU_ASSERT(cp210x_set_line_ctl(p_cdc, cp210x_internal_control_complete, - PROCESS_CONFIG_STATE(idx, CONFIG_CP210X_SET_DTR_RTS))); + TU_ASSERT(cp210x_set_line_ctl(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_SET_DTR_RTS)); break; #else TU_ATTR_FALLTHROUGH; @@ -1877,8 +1923,7 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) { #ifdef LINE_CONTROL_ON_ENUM p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; p_cdc->user_control_cb = cdch_process_set_config; - TU_ASSERT(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, - PROCESS_CONFIG_STATE(idx, CONFIG_CP210X_COMPLETE))); + TU_ASSERT(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; @@ -2108,7 +2153,7 @@ static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, ui } static bool ch34x_process_set_config(tuh_xfer_t *xfer) { - const uint8_t state = (uint8_t) xfer->user_data; + const uintptr_t state = xfer->user_data; uint8_t const itf_num = 0; // CH34x has only interface 0, since wIndex is used as payload uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t *p_cdc = get_itf(idx); @@ -2119,7 +2164,7 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { switch (state) { case CONFIG_CH34X_READ_VERSION: TU_ASSERT(ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_CH34X_SERIAL_INIT))); + cdch_process_set_config, CONFIG_CH34X_SERIAL_INIT)); break; case CONFIG_CH34X_SERIAL_INIT: { @@ -2135,7 +2180,7 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { uint8_t const lcr = ch34x_get_lcr(p_cdc); TU_ASSERT(div_ps != 0 && lcr != 0); TU_ASSERT(ch34x_control_out(p_cdc, CH34X_REQ_SERIAL_INIT, tu_u16(lcr, 0x9c), div_ps, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_CH34X_SPECIAL_REG_WRITE))); + cdch_process_set_config, CONFIG_CH34X_SPECIAL_REG_WRITE)); } break; } @@ -2144,20 +2189,20 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { // overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver p_cdc->line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; TU_ASSERT(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_CH34X_FLOW_CONTROL))); + cdch_process_set_config, CONFIG_CH34X_FLOW_CONTROL)); break; case CONFIG_CH34X_FLOW_CONTROL: // no hardware flow control TU_ASSERT(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x27, CH341_REG_0x27), 0x0000, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_CH34X_MODEM_CONTROL))); + cdch_process_set_config, CONFIG_CH34X_MODEM_CONTROL)); break; case CONFIG_CH34X_MODEM_CONTROL: #ifdef LINE_CONTROL_ON_ENUM p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; p_cdc->user_control_cb = cdch_process_set_config; - TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, PROCESS_CONFIG_STATE(idx, CONFIG_CH34X_COMPLETE))); + TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; @@ -2511,7 +2556,7 @@ static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui } static bool pl2303_process_set_config(tuh_xfer_t *xfer) { - const uint8_t state = (uint8_t) xfer->user_data; + const uintptr_t state = xfer->user_data; // PL2303 has only interface 0, because wIndex is used as payload and not for bInterfaceNumber uint8_t const itf_num = 0; uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); @@ -2527,12 +2572,12 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { p_cdc->user_control_cb = cdch_process_set_config;// set once for whole process config // get device descriptor TU_ASSERT(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_DETECT_TYPE))); + cdch_process_set_config, CONFIG_PL2303_DETECT_TYPE)); break; case CONFIG_PL2303_DETECT_TYPE: // get type and quirks (step 1) - type = pl2303_detect_type(p_cdc, 1, cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ1)); + type = pl2303_detect_type(p_cdc, 1, cdch_process_set_config, CONFIG_PL2303_READ1); TU_ASSERT(type != PL2303_DETECT_TYPE_FAILED); if (type == PL2303_SUPPORTS_HX_STATUS_TRIGGERED) { break; @@ -2559,8 +2604,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { #endif // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_WRITE1))); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE1)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2568,8 +2612,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE1: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT(pl2303_vendor_write(p_cdc, 0x0404, 0, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ2))); + TU_ASSERT(pl2303_vendor_write(p_cdc, 0x0404, 0, cdch_process_set_config, CONFIG_PL2303_READ2)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2577,8 +2620,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ2: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ3))); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_READ3)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2586,8 +2628,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ3: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ4))); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, cdch_process_set_config, CONFIG_PL2303_READ4)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2595,8 +2636,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ4: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_WRITE2))); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE2)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2604,8 +2644,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE2: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT(pl2303_vendor_write(p_cdc, 0x0404, 1, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ5))); + TU_ASSERT(pl2303_vendor_write(p_cdc, 0x0404, 1, cdch_process_set_config, CONFIG_PL2303_READ5)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2613,8 +2652,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ5: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_READ6))); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_READ6)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2622,8 +2660,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ6: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_WRITE3))); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE3)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2631,8 +2668,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE3: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT(pl2303_vendor_write(p_cdc, 0, 1, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_WRITE4))); + TU_ASSERT(pl2303_vendor_write(p_cdc, 0, 1, cdch_process_set_config, CONFIG_PL2303_WRITE4)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2640,8 +2676,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE4: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { - TU_ASSERT(pl2303_vendor_write(p_cdc, 1, 0, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_WRITE5))); + TU_ASSERT(pl2303_vendor_write(p_cdc, 1, 0, cdch_process_set_config, CONFIG_PL2303_WRITE5)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2650,8 +2685,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { uint16_t const windex = (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) ? 0x24 : 0x44; - TU_ASSERT(pl2303_vendor_write(p_cdc, 2, windex, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_RESET_ENDP1))); + TU_ASSERT(pl2303_vendor_write(p_cdc, 2, windex, cdch_process_set_config, CONFIG_PL2303_RESET_ENDP1)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2660,17 +2694,15 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_RESET_ENDP1: // step 1 if (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) { - TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_OUT_EP, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_RESET_ENDP2))); + TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_OUT_EP, cdch_process_set_config, CONFIG_PL2303_RESET_ENDP2)); } else { /* reset upstream data pipes */ if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { TU_ASSERT(pl2303_vendor_write(p_cdc, PL2303_HXN_RESET_REG,// skip CONFIG_PL2303_RESET_ENDP2, no 2nd step PL2303_HXN_RESET_UPSTREAM_PIPE | PL2303_HXN_RESET_DOWNSTREAM_PIPE, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_LINE_CODING))); + cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); } else { - pl2303_vendor_write(p_cdc, 8, 0, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_RESET_ENDP2)); + pl2303_vendor_write(p_cdc, 8, 0, cdch_process_set_config, CONFIG_PL2303_RESET_ENDP2); } } break; @@ -2678,15 +2710,13 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_RESET_ENDP2: // step 2 if (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) { - TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_IN_EP, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_LINE_CODING))); + TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_IN_EP, cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); } else { /* reset upstream data pipes */ if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { // here nothing to do, only structure of previous step overtaken for better reading and comparison } else { - TU_ASSERT(pl2303_vendor_write(p_cdc, 9, 0, - cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_LINE_CODING))); + TU_ASSERT(pl2303_vendor_write(p_cdc, 9, 0, cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); } } break; @@ -2696,8 +2726,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_LINE_CODING: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(pl2303_set_line_request(p_cdc, pl2303_internal_control_complete, - PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_MODEM_CONTROL))); + TU_ASSERT(pl2303_set_line_request(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_MODEM_CONTROL)); break; #else TU_ATTR_FALLTHROUGH; @@ -2706,8 +2735,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_MODEM_CONTROL: #ifdef LINE_CONTROL_ON_ENUM p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; - TU_ASSERT(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, - PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_COMPLETE))); + TU_ASSERT(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; @@ -2719,7 +2747,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { // if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { // TU_LOG_P_CDC ( "1\r\n" ); // TU_ASSERT(pl2303_vendor_read(p_cdc, PL2303_HXN_FLOWCTRL_REG, &buf, - // cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_FLOW_CTRL_WRITE))); + // cdch_process_set_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); // } else { // TU_LOG_P_CDC ( "2\r\n" ); // TU_ASSERT(pl2303_vendor_read(p_cdc, 0, &buf, cdch_process_set_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); @@ -2733,11 +2761,11 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { // buf &= (uint8_t) ~PL2303_HXN_FLOWCTRL_MASK; // buf |= PL2303_HXN_FLOWCTRL_NONE; // TU_ASSERT(pl2303_vendor_write(p_cdc, PL2303_HXN_FLOWCTRL_REG, buf, - // cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_COMPLETE))); + // cdch_process_set_config, CONFIG_PL2303_COMPLETE)); // } else { // buf &= (uint8_t) ~PL2303_FLOWCTRL_MASK; // TU_ASSERT(pl2303_vendor_write(p_cdc, 0, buf, - // cdch_process_set_config, PROCESS_CONFIG_STATE(idx, CONFIG_PL2303_COMPLETE))); + // cdch_process_set_config, CONFIG_PL2303_COMPLETE)); // } // break; From 9503883ba7f99523a14082ce68a5f900585747b0 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 18 Jun 2025 23:35:44 +0700 Subject: [PATCH 230/382] usbh: add new API tuh_descriptor_get_device_local() cdc host: remove the local desc_dev and the get_device descriptor call for ftdi and pl2303 --- src/class/cdc/cdc_host.c | 141 ++++++++++++--------------------------- src/common/tusb_types.h | 1 - src/host/usbh.c | 58 ++++++++++++---- src/host/usbh.h | 3 + 4 files changed, 91 insertions(+), 112 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 3be61e654..d704d82d7 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -123,10 +123,6 @@ typedef struct { static cdch_interface_t cdch_data[CFG_TUH_CDC]; CFG_TUH_MEM_SECTION static cdch_epbuf_t cdch_epbuf[CFG_TUH_CDC]; -#if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_PL2303 - static tusb_desc_device_t desc_dev[CFG_TUH_ENUMERATION_BUFSIZE]; -#endif - //--------------------------------------------------------------------+ // Serial Driver //--------------------------------------------------------------------+ @@ -189,8 +185,6 @@ static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complet static uint16_t const pl2303_vid_pid_list[][2] = {CFG_TUH_CDC_PL2303_VID_PID_LIST}; static const struct pl2303_type_data pl2303_type_data[TYPE_COUNT] = {PL2303_TYPE_DATA}; -CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN - static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); static bool pl2303_process_set_config(tuh_xfer_t *xfer); @@ -331,7 +325,7 @@ TU_ATTR_ALWAYS_INLINE static inline cdch_interface_t * get_itf(uint8_t idx) { } TU_ATTR_ALWAYS_INLINE static inline uint8_t get_idx_by_ptr(cdch_interface_t* p_cdc) { - return p_cdc - cdch_data; + return (uint8_t) (p_cdc - cdch_data); } static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) { @@ -434,7 +428,7 @@ bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t * info) { info->daddr = p_cdc->daddr; - // re-construct descriptor + // re-construct interface descriptor tusb_desc_interface_t * desc = &info->desc; desc->bLength = sizeof(tusb_desc_interface_t); desc->bDescriptorType = TUSB_DESC_INTERFACE; @@ -975,8 +969,6 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { // ACM //--------------------------------------------------------------------+ -//------------- Driver API -------------// - // internal control complete to update state such as line state, encoding static void acm_internal_control_complete(tuh_xfer_t *xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); @@ -1089,7 +1081,6 @@ static bool acm_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, } //------------- Enumeration -------------// - enum { CONFIG_ACM_SET_CONTROL_LINE_STATE = 0, CONFIG_ACM_SET_LINE_CODING, @@ -1339,8 +1330,7 @@ static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ //------------- Enumeration -------------// enum { - CONFIG_FTDI_GET_DESC = 0, - CONFIG_FTDI_DETERMINE_TYPE, + CONFIG_FTDI_DETERMINE_TYPE = 0, CONFIG_FTDI_WRITE_LATENCY, CONFIG_FTDI_SIO_RESET, CONFIG_FTDI_SET_DATA, @@ -1383,15 +1373,6 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { switch (state) { // from here sequence overtaken from Linux Kernel function ftdi_port_probe() - case CONFIG_FTDI_GET_DESC: - // get device descriptor - if (itf_num == 0) { // only necessary for 1st interface. other interface overtake type from interface 0 - TU_ASSERT(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), - cdch_process_set_config, CONFIG_FTDI_DETERMINE_TYPE)); - break; - } - TU_ATTR_FALLTHROUGH; - case CONFIG_FTDI_DETERMINE_TYPE: // determine type if (itf_num == 0) { @@ -1472,7 +1453,9 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { //------------- Helper -------------// static bool ftdi_determine_type(cdch_interface_t *p_cdc) { - uint16_t const version = desc_dev->bcdDevice; + tusb_desc_device_t desc_dev; + TU_VERIFY(tuh_descriptor_get_device_local(p_cdc->daddr, &desc_dev)); + uint16_t const version = desc_dev.bcdDevice; uint8_t const itf_num = p_cdc->bInterfaceNumber; p_cdc->ftdi.chip_type = UNKNOWN; @@ -1482,8 +1465,7 @@ static bool ftdi_determine_type(cdch_interface_t *p_cdc) { switch (version) { case 0x200: - // FT232A not supported to keep it simple (no extra _read_latency_timer()) - // not testable + // FT232A not supported to keep it simple (no extra _read_latency_timer()) not testable // p_cdc->ftdi.chip_type = FT232A; // p_cdc->ftdi.baud_base = 48000000 / 2; // p_cdc->ftdi.channel = 0; @@ -1497,50 +1479,20 @@ static bool ftdi_determine_type(cdch_interface_t *p_cdc) { // p_cdc->ftdi.chip_type = FT232B; // } break; - case 0x400: - p_cdc->ftdi.chip_type = FT232B; - p_cdc->ftdi.channel = 0; - break; - case 0x500: - p_cdc->ftdi.chip_type = FT2232C; - break; - case 0x600: - p_cdc->ftdi.chip_type = FT232R; - p_cdc->ftdi.channel = 0; - break; - case 0x700: - p_cdc->ftdi.chip_type = FT2232H; - break; - case 0x800: - p_cdc->ftdi.chip_type = FT4232H; - break; - case 0x900: - p_cdc->ftdi.chip_type = FT232H; - break; - case 0x1000: - p_cdc->ftdi.chip_type = FTX; - break; - case 0x2800: - p_cdc->ftdi.chip_type = FT2233HP; - break; - case 0x2900: - p_cdc->ftdi.chip_type = FT4233HP; - break; - case 0x3000: - p_cdc->ftdi.chip_type = FT2232HP; - break; - case 0x3100: - p_cdc->ftdi.chip_type = FT4232HP; - break; - case 0x3200: - p_cdc->ftdi.chip_type = FT233HP; - break; - case 0x3300: - p_cdc->ftdi.chip_type = FT232HP; - break; - case 0x3600: - p_cdc->ftdi.chip_type = FT4232HA; - break; + case 0x400: p_cdc->ftdi.chip_type = FT232B; p_cdc->ftdi.channel = 0; break; + case 0x500: p_cdc->ftdi.chip_type = FT2232C; break; + case 0x600: p_cdc->ftdi.chip_type = FT232R; p_cdc->ftdi.channel = 0; break; + case 0x700: p_cdc->ftdi.chip_type = FT2232H; break; + case 0x800: p_cdc->ftdi.chip_type = FT4232H; break; + case 0x900: p_cdc->ftdi.chip_type = FT232H; break; + case 0x1000: p_cdc->ftdi.chip_type = FTX; break; + case 0x2800: p_cdc->ftdi.chip_type = FT2233HP; break; + case 0x2900: p_cdc->ftdi.chip_type = FT4233HP; break; + case 0x3000: p_cdc->ftdi.chip_type = FT2232HP; break; + case 0x3100: p_cdc->ftdi.chip_type = FT4232HP; break; + case 0x3200: p_cdc->ftdi.chip_type = FT233HP; break; + case 0x3300: p_cdc->ftdi.chip_type = FT232HP; break; + case 0x3600: p_cdc->ftdi.chip_type = FT4232HA; break; default: if (version < 0x200) { p_cdc->ftdi.chip_type = SIO; @@ -1550,7 +1502,7 @@ static bool ftdi_determine_type(cdch_interface_t *p_cdc) { } TU_LOG_P_CDC("%s detected (bcdDevice = 0x%04x)", - ftdi_chip_name[p_cdc->ftdi.chip_type], desc_dev->bcdDevice); + ftdi_chip_name[p_cdc->ftdi.chip_type], version); return (p_cdc->ftdi.chip_type != UNKNOWN); } @@ -2025,7 +1977,8 @@ static bool ch34x_write_reg_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t comp } static bool ch34x_modem_ctrl_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t control = ~((p_cdc->requested_line_state.rts ? CH34X_BIT_RTS : 0) |// CH34x signals are inverted + // CH34x signals are inverted + uint8_t control = ~((p_cdc->requested_line_state.rts ? CH34X_BIT_RTS : 0) | (p_cdc->requested_line_state.dtr ? CH34X_BIT_DTR : 0)); return ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, complete_cb, user_data); } @@ -2506,8 +2459,7 @@ static bool pl2303_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet //------------- Enumeration -------------// enum { - CONFIG_PL2303_GET_DESC = 0, - CONFIG_PL2303_DETECT_TYPE, + CONFIG_PL2303_DETECT_TYPE = 0, CONFIG_PL2303_READ1, CONFIG_PL2303_WRITE1, CONFIG_PL2303_READ2, @@ -2568,14 +2520,8 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { TU_ASSERT(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || xfer->user_data == CONFIG_PL2303_READ1)); switch (state) { // from here sequence overtaken from Linux Kernel function pl2303_startup() - case CONFIG_PL2303_GET_DESC: - p_cdc->user_control_cb = cdch_process_set_config;// set once for whole process config - // get device descriptor - TU_ASSERT(tuh_descriptor_get_device(xfer->daddr, &desc_dev, sizeof(tusb_desc_device_t), - cdch_process_set_config, CONFIG_PL2303_DETECT_TYPE)); - break; - case CONFIG_PL2303_DETECT_TYPE: + p_cdc->user_control_cb = cdch_process_set_config;// set once for whole process config // get type and quirks (step 1) type = pl2303_detect_type(p_cdc, 1, cdch_process_set_config, CONFIG_PL2303_READ1); TU_ASSERT(type != PL2303_DETECT_TYPE_FAILED); @@ -2784,39 +2730,39 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - /* - * Legacy PL2303H, variants 0 and 1 (difference unknown). - */ - if (desc_dev->bDeviceClass == 0x02) { + tusb_desc_device_t desc_dev; + TU_VERIFY(tuh_descriptor_get_device_local(p_cdc->daddr, &desc_dev), PL2303_DETECT_TYPE_FAILED); + + // Legacy PL2303H, variants 0 and 1 (difference unknown). + if (desc_dev.bDeviceClass == 0x02) { return TYPE_H; /* variant 0 */ } - if (desc_dev->bMaxPacketSize0 != 0x40) { - if (desc_dev->bDeviceClass == 0x00 || desc_dev->bDeviceClass == 0xff) { + if (desc_dev.bMaxPacketSize0 != 0x40) { + if (desc_dev.bDeviceClass == 0x00 || desc_dev.bDeviceClass == 0xff) { return TYPE_H; /* variant 1 */ } return TYPE_H; /* variant 0 */ } - switch (desc_dev->bcdUSB) { + switch (desc_dev.bcdUSB) { case 0x101: /* USB 1.0.1? Let's assume they meant 1.1... */ TU_ATTR_FALLTHROUGH; case 0x110: - switch (desc_dev->bcdDevice) { - case 0x300: - return TYPE_HX; - case 0x400: - return TYPE_HXD; - default: - return TYPE_HX; + switch (desc_dev.bcdDevice) { + case 0x300: return TYPE_HX; + case 0x400: return TYPE_HXD; + default: return TYPE_HX; } break; + case 0x200: - switch (desc_dev->bcdDevice) { + switch (desc_dev.bcdDevice) { case 0x100: /* GC */ case 0x105: return TYPE_HXN; + case 0x300: /* GT / TA */ if (step == 1) { // step 1 trigger pl2303_supports_hx_status() request @@ -2833,6 +2779,7 @@ static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, case 0x400: /* GL */ case 0x405: return TYPE_HXN; + case 0x500: /* GE / TB */ if (step == 1) { // step 1 trigger pl2303_supports_hx_status() request @@ -2851,6 +2798,7 @@ static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, case 0x700: /* GR */ case 0x705: return TYPE_HXN; + default: break; } @@ -2858,8 +2806,7 @@ static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, default: break; } - TU_LOG_P_CDC("unknown device type bcdUSB = 0x%04x", desc_dev->bcdUSB); - + TU_LOG_P_CDC("unknown device type bcdUSB = 0x%04x", desc_dev.bcdUSB); return PL2303_DETECT_TYPE_FAILED; } diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index fd7f01b67..ff5d8b66a 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -345,7 +345,6 @@ typedef struct TU_ATTR_PACKED { uint8_t iManufacturer ; ///< Index of string descriptor describing manufacturer. uint8_t iProduct ; ///< Index of string descriptor describing product. uint8_t iSerialNumber ; ///< Index of string descriptor describing the device's serial number. - uint8_t bNumConfigurations ; ///< Number of possible configurations. } tusb_desc_device_t; diff --git a/src/host/usbh.c b/src/host/usbh.c index f2e5c1f0e..08c362171 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -94,6 +94,20 @@ TU_ATTR_WEAK bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_si typedef struct { tuh_bus_info_t bus_info; + // Device Descriptor + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; + // Device State struct TU_ATTR_PACKED { volatile uint8_t connected : 1; // After 1st transfer @@ -103,18 +117,6 @@ typedef struct { // volatile uint8_t removing : 1; // Physically disconnected, waiting to be processed by usbh }; - // Device Descriptor - uint8_t ep0_size; - uint16_t idVendor; - uint16_t idProduct; - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; - - // Configuration Descriptor - // uint8_t interface_count; // bNumInterfaces alias - // Endpoint & Interface uint8_t itf2drv[CFG_TUH_INTERFACE_MAX]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUH_ENDPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each @@ -373,6 +375,28 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid) { return true; } +bool tuh_descriptor_get_device_local(uint8_t daddr, tusb_desc_device_t* desc_device) { + usbh_device_t *dev = get_device(daddr); + TU_VERIFY(dev && desc_device); + + desc_device->bLength = sizeof(tusb_desc_device_t); + desc_device->bDescriptorType = TUSB_DESC_DEVICE; + desc_device->bcdUSB = dev->bcdUSB; + desc_device->bDeviceClass = dev->bDeviceClass; + desc_device->bDeviceSubClass = dev->bDeviceSubClass; + desc_device->bDeviceProtocol = dev->bDeviceProtocol; + desc_device->bMaxPacketSize0 = dev->bMaxPacketSize0; + desc_device->idVendor = dev->idVendor; + desc_device->idProduct = dev->idProduct; + desc_device->bcdDevice = dev->bcdDevice; + desc_device->iManufacturer = dev->iManufacturer; + desc_device->iProduct = dev->iProduct; + desc_device->iSerialNumber = dev->iSerialNumber; + desc_device->bNumConfigurations = dev->bNumConfigurations; + + return true; +} + tusb_speed_t tuh_speed_get(uint8_t daddr) { tuh_bus_info_t bus_info; tuh_bus_info_get(daddr, &bus_info); @@ -1579,7 +1603,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { usbh_device_t* new_dev = get_device(new_addr); new_dev->bus_info = *dev0_bus; new_dev->connected = 1; - new_dev->ep0_size = desc_device->bMaxPacketSize0; + new_dev->bMaxPacketSize0 = desc_device->bMaxPacketSize0; TU_ASSERT(tuh_address_set(0, new_addr, process_enumeration, ENUM_GET_DEVICE_DESC),); break; @@ -1596,7 +1620,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { usbh_device_close(dev0_bus->rhport, 0); // close dev0 - TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->ep0_size),); // open new control endpoint + TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->bMaxPacketSize0),); // open new control endpoint TU_LOG_USBH("Get Device Descriptor\r\n"); TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_epbuf.ctrl, sizeof(tusb_desc_device_t), @@ -1609,8 +1633,14 @@ static void process_enumeration(tuh_xfer_t* xfer) { case ENUM_GET_STRING_LANGUAGE_ID_LEN: { // save the received device descriptor tusb_desc_device_t const *desc_device = (tusb_desc_device_t const *) _usbh_epbuf.ctrl; + dev->bcdUSB = desc_device->bcdUSB; + dev->bDeviceClass = desc_device->bDeviceClass; + dev->bDeviceSubClass = desc_device->bDeviceSubClass; + dev->bDeviceProtocol = desc_device->bDeviceProtocol; + dev->bMaxPacketSize0 = desc_device->bMaxPacketSize0; dev->idVendor = desc_device->idVendor; dev->idProduct = desc_device->idProduct; + dev->bcdDevice = desc_device->bcdDevice; dev->iManufacturer = desc_device->iManufacturer; dev->iProduct = desc_device->iProduct; dev->iSerialNumber = desc_device->iSerialNumber; diff --git a/src/host/usbh.h b/src/host/usbh.h index 13eede869..1ee511722 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -204,6 +204,9 @@ bool tuh_rhport_reset_bus(uint8_t rhport, bool active); // Get VID/PID of device bool tuh_vid_pid_get(uint8_t daddr, uint16_t* vid, uint16_t* pid); +// Get local (cached) device descriptor once device is enumerated +bool tuh_descriptor_get_device_local(uint8_t daddr, tusb_desc_device_t* desc_device); + // Get speed of device tusb_speed_t tuh_speed_get(uint8_t daddr); From 2adb305ea71f69b38c6c01cc054d8e323dd25e0e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Jun 2025 15:30:02 +0700 Subject: [PATCH 231/382] house keeping --- src/class/cdc/cdc_host.c | 183 ++++++++++++++++---------------- src/class/cdc/serial/ftdi_sio.h | 74 ++++++------- src/class/cdc/serial/pl2303.h | 40 +++---- 3 files changed, 150 insertions(+), 147 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index d704d82d7..ce98e3b3d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -111,13 +111,13 @@ typedef struct { tu_edpt_stream_t rx; uint8_t tx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE]; - uint8_t rx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE]; + uint8_t rx_ff_buf[CFG_TUH_CDC_RX_BUFSIZE]; } stream; } cdch_interface_t; typedef struct { TUH_EPBUF_DEF(tx, CFG_TUH_CDC_TX_EPSIZE); - TUH_EPBUF_DEF(rx, CFG_TUH_CDC_TX_EPSIZE); + TUH_EPBUF_DEF(rx, CFG_TUH_CDC_RX_EPSIZE); } cdch_epbuf_t; static cdch_interface_t cdch_data[CFG_TUH_CDC]; @@ -141,10 +141,6 @@ static bool acm_set_control_line_state(cdch_interface_t * p_cdc, tuh_xfer_cb_t c //------------- FTDI prototypes -------------// #if CFG_TUH_CDC_FTDI static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST}; -#if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - static uint8_t const * ftdi_chip_name[] = { FTDI_CHIP_NAMES }; -#endif - static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); static bool ftdi_proccess_set_config(tuh_xfer_t * xfer); @@ -183,7 +179,7 @@ static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complet //------------- PL2303 prototypes -------------// #if CFG_TUH_CDC_PL2303 static uint16_t const pl2303_vid_pid_list[][2] = {CFG_TUH_CDC_PL2303_VID_PID_LIST}; -static const struct pl2303_type_data pl2303_type_data[TYPE_COUNT] = {PL2303_TYPE_DATA}; +static const pl2303_type_data_t pl2303_type_data[PL2303_TYPE_COUNT] = {PL2303_TYPE_DATA}; static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); static bool pl2303_process_set_config(tuh_xfer_t *xfer); @@ -1209,7 +1205,7 @@ static bool ftdi_set_request(cdch_interface_t *p_cdc, uint8_t request, uint8_t r #ifdef CFG_TUH_CDC_FTDI_LATENCY static int8_t ftdi_write_latency_timer(cdch_interface_t * p_cdc, uint16_t latency, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - if (p_cdc->ftdi.chip_type == SIO /* || p_cdc->ftdi.chip_type == FT232A */ ) + if (p_cdc->ftdi.chip_type == FTDI_SIO /* || p_cdc->ftdi.chip_type == FT232A */ ) return FTDI_NOT_POSSIBLE; return ftdi_set_request(p_cdc, FTDI_SIO_SET_LATENCY_TIMER_REQUEST, FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, latency, p_cdc->ftdi.channel, complete_cb, user_data) ? FTDI_REQUESTED : FTDI_FAIL; @@ -1458,7 +1454,7 @@ static bool ftdi_determine_type(cdch_interface_t *p_cdc) { uint16_t const version = desc_dev.bcdDevice; uint8_t const itf_num = p_cdc->bInterfaceNumber; - p_cdc->ftdi.chip_type = UNKNOWN; + p_cdc->ftdi.chip_type = FTDI_UNKNOWN; /* Assume Hi-Speed type */ p_cdc->ftdi.channel = CHANNEL_A + itf_num; @@ -1476,35 +1472,40 @@ static bool ftdi_determine_type(cdch_interface_t *p_cdc) { // */ // if (desc->iSerialNumber == 0 && // _read_latency_timer(port) >= 0) { - // p_cdc->ftdi.chip_type = FT232B; + // p_cdc->ftdi.chip_type = FTDI_FT232B; // } break; - case 0x400: p_cdc->ftdi.chip_type = FT232B; p_cdc->ftdi.channel = 0; break; - case 0x500: p_cdc->ftdi.chip_type = FT2232C; break; - case 0x600: p_cdc->ftdi.chip_type = FT232R; p_cdc->ftdi.channel = 0; break; - case 0x700: p_cdc->ftdi.chip_type = FT2232H; break; - case 0x800: p_cdc->ftdi.chip_type = FT4232H; break; - case 0x900: p_cdc->ftdi.chip_type = FT232H; break; - case 0x1000: p_cdc->ftdi.chip_type = FTX; break; - case 0x2800: p_cdc->ftdi.chip_type = FT2233HP; break; - case 0x2900: p_cdc->ftdi.chip_type = FT4233HP; break; - case 0x3000: p_cdc->ftdi.chip_type = FT2232HP; break; - case 0x3100: p_cdc->ftdi.chip_type = FT4232HP; break; - case 0x3200: p_cdc->ftdi.chip_type = FT233HP; break; - case 0x3300: p_cdc->ftdi.chip_type = FT232HP; break; - case 0x3600: p_cdc->ftdi.chip_type = FT4232HA; break; + + case 0x400 : p_cdc->ftdi.chip_type = FTDI_FT232B; p_cdc->ftdi.channel = 0; break; + case 0x500 : p_cdc->ftdi.chip_type = FTDI_FT2232C; break; + case 0x600 : p_cdc->ftdi.chip_type = FTDI_FT232R; p_cdc->ftdi.channel = 0; break; + case 0x700 : p_cdc->ftdi.chip_type = FTDI_FT2232H; break; + case 0x800 : p_cdc->ftdi.chip_type = FTDI_FT4232H; break; + case 0x900 : p_cdc->ftdi.chip_type = FTDI_FT232H; break; + case 0x1000: p_cdc->ftdi.chip_type = FTDI_FTX; break; + case 0x2800: p_cdc->ftdi.chip_type = FTDI_FT2233HP; break; + case 0x2900: p_cdc->ftdi.chip_type = FTDI_FT4233HP; break; + case 0x3000: p_cdc->ftdi.chip_type = FTDI_FT2232HP; break; + case 0x3100: p_cdc->ftdi.chip_type = FTDI_FT4232HP; break; + case 0x3200: p_cdc->ftdi.chip_type = FTDI_FT233HP; break; + case 0x3300: p_cdc->ftdi.chip_type = FTDI_FT232HP; break; + case 0x3600: p_cdc->ftdi.chip_type = FTDI_FT4232HA; break; + default: if (version < 0x200) { - p_cdc->ftdi.chip_type = SIO; + p_cdc->ftdi.chip_type = FTDI_SIO; p_cdc->ftdi.channel = 0; } break; } + #if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL + const char * ftdi_chip_name[] = { FTDI_CHIP_NAMES }; TU_LOG_P_CDC("%s detected (bcdDevice = 0x%04x)", ftdi_chip_name[p_cdc->ftdi.chip_type], version); + #endif - return (p_cdc->ftdi.chip_type != UNKNOWN); + return (p_cdc->ftdi.chip_type != FTDI_UNKNOWN); } // FT232A not supported @@ -1589,9 +1590,9 @@ static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { TU_VERIFY(baud); switch (p_cdc->ftdi.chip_type) { - case UNKNOWN: + case FTDI_UNKNOWN: return 0; - case SIO: + case FTDI_SIO: switch (baud) { case 300: div_value = ftdi_sio_b300; break; case 600: div_value = ftdi_sio_b600; break; @@ -1620,23 +1621,23 @@ static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { // div_okay = false; // } // break; - case FT232B: - case FT2232C: - case FT232R: - case FTX: + case FTDI_FT232B: + case FTDI_FT2232C: + case FTDI_FT232R: + case FTDI_FTX: TU_VERIFY(baud <= 3000000); // else Baud rate too high! div_value = ftdi_232bm_baud_to_divisor(baud); break; - case FT232H: - case FT2232H: - case FT4232H: - case FT4232HA: - case FT232HP: - case FT233HP: - case FT2232HP: - case FT2233HP: - case FT4232HP: - case FT4233HP: + case FTDI_FT232H: + case FTDI_FT2232H: + case FTDI_FT4232H: + case FTDI_FT4232HA: + case FTDI_FT232HP: + case FTDI_FT233HP: + case FTDI_FT2232HP: + case FTDI_FT2233HP: + case FTDI_FT4232HP: + case FTDI_FT4233HP: default: TU_VERIFY(baud <= 12000000); // else Baud rate too high! if (baud >= 1200) { @@ -2273,8 +2274,7 @@ static uint8_t ch34x_get_lcr(cdch_interface_t *p_cdc) { //--------------------------------------------------------------------+ #if CFG_TUH_CDC_PL2303 -static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, - tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step); static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]); //------------- Control Request -------------// @@ -2313,14 +2313,13 @@ static bool pl2303_set_request(cdch_interface_t *p_cdc, uint8_t request, uint8_t static bool pl2303_vendor_read(cdch_interface_t *p_cdc, uint16_t value, uint8_t *buf, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN] ? PL2303_VENDOR_READ_NREQUEST : PL2303_VENDOR_READ_REQUEST; - + uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN] ? PL2303_VENDOR_READ_NREQUEST : PL2303_VENDOR_READ_REQUEST; return pl2303_set_request(p_cdc, request, PL2303_VENDOR_READ_REQUEST_TYPE, value, 0, buf, 1, complete_cb, user_data); } static bool pl2303_vendor_write(cdch_interface_t *p_cdc, uint16_t value, uint16_t index, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN] ? PL2303_VENDOR_WRITE_NREQUEST : PL2303_VENDOR_WRITE_REQUEST; + uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN] ? PL2303_VENDOR_WRITE_NREQUEST : PL2303_VENDOR_WRITE_REQUEST; return pl2303_set_request(p_cdc, request, PL2303_VENDOR_WRITE_REQUEST_TYPE, value, index, NULL, 0, complete_cb, user_data); } @@ -2517,25 +2516,30 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { uint8_t buf = 0; int8_t type; - TU_ASSERT(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || xfer->user_data == CONFIG_PL2303_READ1)); + TU_ASSERT(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || state == CONFIG_PL2303_READ1)); switch (state) { // from here sequence overtaken from Linux Kernel function pl2303_startup() case CONFIG_PL2303_DETECT_TYPE: p_cdc->user_control_cb = cdch_process_set_config;// set once for whole process config // get type and quirks (step 1) - type = pl2303_detect_type(p_cdc, 1, cdch_process_set_config, CONFIG_PL2303_READ1); - TU_ASSERT(type != PL2303_DETECT_TYPE_FAILED); - if (type == PL2303_SUPPORTS_HX_STATUS_TRIGGERED) { + type = pl2303_detect_type(p_cdc, 1); + TU_ASSERT(type != PL2303_TYPE_UNKNOWN); + if (type == PL2303_TYPE_NEED_SUPPORTS_HX_STATUS) { + TU_ASSERT(pl2303_supports_hx_status(p_cdc, cdch_process_set_config, CONFIG_PL2303_READ1)); break; - }// else: no transfer triggered and continue with CONFIG_PL2303_READ1 - TU_ATTR_FALLTHROUGH; + } else { + // no transfer triggered and continue with CONFIG_PL2303_READ1 + TU_ATTR_FALLTHROUGH; + } case CONFIG_PL2303_READ1: // get supports_hx_status, type and quirks (step 2), do special read - p_cdc->pl2303.supports_hx_status = (// will not be true, if coming directly from previous case - xfer->user_data == CONFIG_PL2303_READ1 && xfer->result == XFER_RESULT_SUCCESS); - type = pl2303_detect_type(p_cdc, 2, NULL, 0); // step 2 now with supports_hx_status - TU_ASSERT(type != PL2303_DETECT_TYPE_FAILED); + // will not be true, if coming directly from previous case + if (xfer->user_data == CONFIG_PL2303_READ1 && xfer->result == XFER_RESULT_SUCCESS) { + p_cdc->pl2303.supports_hx_status = true; + } + type = pl2303_detect_type(p_cdc, 2); // step 2 now with supports_hx_status + TU_ASSERT(type != PL2303_TYPE_UNKNOWN); p_cdc->pl2303.serial_private.type = &pl2303_type_data[type]; p_cdc->pl2303.serial_private.quirks |= p_cdc->pl2303.serial_private.type->quirks; #if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL && 0// can be activated if necessary @@ -2549,7 +2553,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { p_cdc->pl2303.serial_private.type->name, p_cdc->pl2303.serial_private.quirks); #endif // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE1)); break; }// else: continue with next step @@ -2557,7 +2561,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE1: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { TU_ASSERT(pl2303_vendor_write(p_cdc, 0x0404, 0, cdch_process_set_config, CONFIG_PL2303_READ2)); break; }// else: continue with next step @@ -2565,7 +2569,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ2: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_READ3)); break; }// else: continue with next step @@ -2573,7 +2577,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ3: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, cdch_process_set_config, CONFIG_PL2303_READ4)); break; }// else: continue with next step @@ -2581,7 +2585,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ4: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE2)); break; }// else: continue with next step @@ -2589,7 +2593,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE2: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { TU_ASSERT(pl2303_vendor_write(p_cdc, 0x0404, 1, cdch_process_set_config, CONFIG_PL2303_READ5)); break; }// else: continue with next step @@ -2597,7 +2601,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ5: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_READ6)); break; }// else: continue with next step @@ -2605,7 +2609,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ6: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE3)); break; }// else: continue with next step @@ -2613,7 +2617,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE3: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { TU_ASSERT(pl2303_vendor_write(p_cdc, 0, 1, cdch_process_set_config, CONFIG_PL2303_WRITE4)); break; }// else: continue with next step @@ -2621,7 +2625,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE4: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { TU_ASSERT(pl2303_vendor_write(p_cdc, 1, 0, cdch_process_set_config, CONFIG_PL2303_WRITE5)); break; }// else: continue with next step @@ -2629,7 +2633,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE5: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { uint16_t const windex = (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) ? 0x24 : 0x44; TU_ASSERT(pl2303_vendor_write(p_cdc, 2, windex, cdch_process_set_config, CONFIG_PL2303_RESET_ENDP1)); break; @@ -2643,7 +2647,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_OUT_EP, cdch_process_set_config, CONFIG_PL2303_RESET_ENDP2)); } else { /* reset upstream data pipes */ - if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN]) { TU_ASSERT(pl2303_vendor_write(p_cdc, PL2303_HXN_RESET_REG,// skip CONFIG_PL2303_RESET_ENDP2, no 2nd step PL2303_HXN_RESET_UPSTREAM_PIPE | PL2303_HXN_RESET_DOWNSTREAM_PIPE, cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); @@ -2659,7 +2663,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_IN_EP, cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); } else { /* reset upstream data pipes */ - if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { + if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN]) { // here nothing to do, only structure of previous step overtaken for better reading and comparison } else { TU_ASSERT(pl2303_vendor_write(p_cdc, 9, 0, cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); @@ -2690,7 +2694,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { // skipped, because it's not working with each PL230x. flow control can be also set by PL2303 EEPROM Writer Program // case CONFIG_PL2303_FLOW_CTRL_READ: // // read flow control register for modify & write back in next step - // if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { + // if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN]) { // TU_LOG_P_CDC ( "1\r\n" ); // TU_ASSERT(pl2303_vendor_read(p_cdc, PL2303_HXN_FLOWCTRL_REG, &buf, // cdch_process_set_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); @@ -2703,7 +2707,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { // case CONFIG_PL2303_FLOW_CTRL_WRITE: // // no flow control // buf = xfer->buffer[0]; - // if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[TYPE_HXN]) { + // if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN]) { // buf &= (uint8_t) ~PL2303_HXN_FLOWCTRL_MASK; // buf |= PL2303_HXN_FLOWCTRL_NONE; // TU_ASSERT(pl2303_vendor_write(p_cdc, PL2303_HXN_FLOWCTRL_REG, buf, @@ -2728,21 +2732,20 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { //------------- Helper -------------// -static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step) { tusb_desc_device_t desc_dev; - TU_VERIFY(tuh_descriptor_get_device_local(p_cdc->daddr, &desc_dev), PL2303_DETECT_TYPE_FAILED); + TU_VERIFY(tuh_descriptor_get_device_local(p_cdc->daddr, &desc_dev), PL2303_TYPE_UNKNOWN); // Legacy PL2303H, variants 0 and 1 (difference unknown). if (desc_dev.bDeviceClass == 0x02) { - return TYPE_H; /* variant 0 */ + return PL2303_TYPE_H; /* variant 0 */ } if (desc_dev.bMaxPacketSize0 != 0x40) { if (desc_dev.bDeviceClass == 0x00 || desc_dev.bDeviceClass == 0xff) { - return TYPE_H; /* variant 1 */ + return PL2303_TYPE_H; /* variant 1 */ } - return TYPE_H; /* variant 0 */ + return PL2303_TYPE_H; /* variant 0 */ } switch (desc_dev.bcdUSB) { @@ -2751,9 +2754,9 @@ static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, TU_ATTR_FALLTHROUGH; case 0x110: switch (desc_dev.bcdDevice) { - case 0x300: return TYPE_HX; - case 0x400: return TYPE_HXD; - default: return TYPE_HX; + case 0x300: return PL2303_TYPE_HX; + case 0x400: return PL2303_TYPE_HXD; + default: return PL2303_TYPE_HX; } break; @@ -2761,34 +2764,32 @@ static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, switch (desc_dev.bcdDevice) { case 0x100: /* GC */ case 0x105: - return TYPE_HXN; + return PL2303_TYPE_HXN; case 0x300: /* GT / TA */ if (step == 1) { // step 1 trigger pl2303_supports_hx_status() request - TU_ASSERT(pl2303_supports_hx_status(p_cdc, complete_cb, user_data), PL2303_DETECT_TYPE_FAILED); - return PL2303_SUPPORTS_HX_STATUS_TRIGGERED; + return PL2303_TYPE_NEED_SUPPORTS_HX_STATUS; } else { // step 2 use supports_hx_status if (p_cdc->pl2303.supports_hx_status) { - return TYPE_TA; + return PL2303_TYPE_TA; } } TU_ATTR_FALLTHROUGH; case 0x305: case 0x400: /* GL */ case 0x405: - return TYPE_HXN; + return PL2303_TYPE_HXN; case 0x500: /* GE / TB */ if (step == 1) { // step 1 trigger pl2303_supports_hx_status() request - TU_ASSERT(pl2303_supports_hx_status(p_cdc, complete_cb, user_data), PL2303_DETECT_TYPE_FAILED); - return PL2303_SUPPORTS_HX_STATUS_TRIGGERED; + return PL2303_TYPE_NEED_SUPPORTS_HX_STATUS; } else { // step 2 use supports_hx_status if (p_cdc->pl2303.supports_hx_status) { - return TYPE_TB; + return PL2303_TYPE_TB; } } TU_ATTR_FALLTHROUGH; @@ -2797,7 +2798,7 @@ static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, case 0x605: case 0x700: /* GR */ case 0x705: - return TYPE_HXN; + return PL2303_TYPE_HXN; default: break; @@ -2807,7 +2808,7 @@ static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step, } TU_LOG_P_CDC("unknown device type bcdUSB = 0x%04x", desc_dev.bcdUSB); - return PL2303_DETECT_TYPE_FAILED; + return PL2303_TYPE_UNKNOWN; } /* diff --git a/src/class/cdc/serial/ftdi_sio.h b/src/class/cdc/serial/ftdi_sio.h index f621b3912..8abf74f11 100644 --- a/src/class/cdc/serial/ftdi_sio.h +++ b/src/class/cdc/serial/ftdi_sio.h @@ -165,48 +165,48 @@ enum ftdi_sio_baudrate { #define FTDI_RS_FIFO (1 << 7) // chip types and names -enum ftdi_chip_type { - SIO = 0, -// FT232A, - FT232B, - FT2232C, - FT232R, - FT232H, - FT2232H, - FT4232H, - FT4232HA, - FT232HP, - FT233HP, - FT2232HP, - FT2233HP, - FT4232HP, - FT4233HP, - FTX, - UNKNOWN -}; +typedef enum ftdi_chip_type { + FTDI_SIO = 0, +// FTDI_FT232A, + FTDI_FT232B, + FTDI_FT2232C, + FTDI_FT232R, + FTDI_FT232H, + FTDI_FT2232H, + FTDI_FT4232H, + FTDI_FT4232HA, + FTDI_FT232HP, + FTDI_FT233HP, + FTDI_FT2232HP, + FTDI_FT2233HP, + FTDI_FT4232HP, + FTDI_FT4233HP, + FTDI_FTX, + FTDI_UNKNOWN +} ftdi_chip_type_t; #define FTDI_CHIP_NAMES \ - [SIO] = (uint8_t const*) "SIO", /* the serial part of FT8U100AX */ \ -/* [FT232A] = (uint8_t const*) "FT232A", */ \ - [FT232B] = (uint8_t const*) "FT232B", \ - [FT2232C] = (uint8_t const*) "FT2232C/D", \ - [FT232R] = (uint8_t const*) "FT232R", \ - [FT232H] = (uint8_t const*) "FT232H", \ - [FT2232H] = (uint8_t const*) "FT2232H", \ - [FT4232H] = (uint8_t const*) "FT4232H", \ - [FT4232HA] = (uint8_t const*) "FT4232HA", \ - [FT232HP] = (uint8_t const*) "FT232HP", \ - [FT233HP] = (uint8_t const*) "FT233HP", \ - [FT2232HP] = (uint8_t const*) "FT2232HP", \ - [FT2233HP] = (uint8_t const*) "FT2233HP", \ - [FT4232HP] = (uint8_t const*) "FT4232HP", \ - [FT4233HP] = (uint8_t const*) "FT4233HP", \ - [FTX] = (uint8_t const*) "FT-X", \ - [UNKNOWN] = (uint8_t const*) "UNKNOWN" + [FTDI_SIO] = "SIO", /* the serial part of FT8U100AX */ \ +/* [FTDI_FT232A] = "FT232A", */ \ + [FTDI_FT232B] = "FT232B", \ + [FTDI_FT2232C] = "FT2232C/D", \ + [FTDI_FT232R] = "FT232R", \ + [FTDI_FT232H] = "FT232H", \ + [FTDI_FT2232H] = "FTDI_FT2232H", \ + [FTDI_FT4232H] = "FT4232H", \ + [FTDI_FT4232HA] = "FT4232HA", \ + [FTDI_FT232HP] = "FT232HP", \ + [FTDI_FT233HP] = "FT233HP", \ + [FTDI_FT2232HP] = "FT2232HP", \ + [FTDI_FT2233HP] = "FT2233HP", \ + [FTDI_FT4232HP] = "FT4232HP", \ + [FTDI_FT4233HP] = "FT4233HP", \ + [FTDI_FTX] = "FT-X", \ + [FTDI_UNKNOWN] = "UNKNOWN" // private interface data typedef struct ftdi_private { - enum ftdi_chip_type chip_type; + ftdi_chip_type_t chip_type; uint8_t channel; // channel index, or 0 for legacy types } ftdi_private_t; diff --git a/src/class/cdc/serial/pl2303.h b/src/class/cdc/serial/pl2303.h index d69bdbfae..40311260d 100644 --- a/src/class/cdc/serial/pl2303.h +++ b/src/class/cdc/serial/pl2303.h @@ -96,51 +96,53 @@ #define PL2303_HXN_FLOWCTRL_XON_XOFF 0x0c // type data -enum pl2303_type { - TYPE_H, - TYPE_HX, - TYPE_TA, - TYPE_TB, - TYPE_HXD, - TYPE_HXN, - TYPE_COUNT -}; +typedef enum pl2303_type { + PL2303_TYPE_H, + PL2303_TYPE_HX, + PL2303_TYPE_TA, + PL2303_TYPE_TB, + PL2303_TYPE_HXD, + PL2303_TYPE_HXN, + // PL2303_TYPE_NEED_SUPPORTS_HX_STATUS, + // PL2303_TYPE_UNKNOWN, + PL2303_TYPE_COUNT +} pl2303_type_t; -struct pl2303_type_data { +typedef struct pl2303_type_data { uint8_t const *name; uint32_t const max_baud_rate; uint8_t const quirks; uint16_t const no_autoxonxoff:1; uint16_t const no_divisors:1; uint16_t const alt_divisors:1; -}; +} pl2303_type_data_t; #define PL2303_TYPE_DATA \ - [TYPE_H] = { \ + [PL2303_TYPE_H] = { \ .name = (uint8_t const*)"H", \ .max_baud_rate = 1228800, \ .quirks = PL2303_QUIRK_LEGACY, \ .no_autoxonxoff = true, \ }, \ - [TYPE_HX] = { \ + [PL2303_TYPE_HX] = { \ .name = (uint8_t const*)"HX", \ .max_baud_rate = 6000000, \ }, \ - [TYPE_TA] = { \ + [PL2303_TYPE_TA] = { \ .name = (uint8_t const*)"TA", \ .max_baud_rate = 6000000, \ .alt_divisors = true, \ }, \ - [TYPE_TB] = { \ + [PL2303_TYPE_TB] = { \ .name = (uint8_t const*)"TB", \ .max_baud_rate = 12000000, \ .alt_divisors = true, \ }, \ - [TYPE_HXD] = { \ + [PL2303_TYPE_HXD] = { \ .name = (uint8_t const*)"HXD", \ .max_baud_rate = 12000000, \ }, \ - [TYPE_HXN] = { \ + [PL2303_TYPE_HXN] = { \ .name = (uint8_t const*)"G (HXN)", \ .max_baud_rate = 12000000, \ .no_divisors = true, \ @@ -166,7 +168,7 @@ typedef struct TU_ATTR_PACKED { #define PL2303_IN_EP 0x83 // return values of pl2303_detect_type() -#define PL2303_SUPPORTS_HX_STATUS_TRIGGERED -1 -#define PL2303_DETECT_TYPE_FAILED -2 +#define PL2303_TYPE_NEED_SUPPORTS_HX_STATUS -1 +#define PL2303_TYPE_UNKNOWN -2 #endif // TUSB_PL2303_H From ec1a26251d0161d5e7c11f4ca552af154cf08dbd Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Jun 2025 17:05:21 +0700 Subject: [PATCH 232/382] clean up pl2303 type data --- src/class/cdc/cdc_host.c | 130 +++++++++++++++------------------- src/class/cdc/serial/pl2303.h | 46 ++++-------- 2 files changed, 74 insertions(+), 102 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index ce98e3b3d..dae38ba42 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -2274,7 +2274,7 @@ static uint8_t ch34x_get_lcr(cdch_interface_t *p_cdc) { //--------------------------------------------------------------------+ #if CFG_TUH_CDC_PL2303 -static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step); +static pl2303_type_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step); static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]); //------------- Control Request -------------// @@ -2313,20 +2313,18 @@ static bool pl2303_set_request(cdch_interface_t *p_cdc, uint8_t request, uint8_t static bool pl2303_vendor_read(cdch_interface_t *p_cdc, uint16_t value, uint8_t *buf, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN] ? PL2303_VENDOR_READ_NREQUEST : PL2303_VENDOR_READ_REQUEST; + uint8_t request = p_cdc->pl2303.type == PL2303_TYPE_HXN ? PL2303_VENDOR_READ_NREQUEST : PL2303_VENDOR_READ_REQUEST; return pl2303_set_request(p_cdc, request, PL2303_VENDOR_READ_REQUEST_TYPE, value, 0, buf, 1, complete_cb, user_data); } static bool pl2303_vendor_write(cdch_interface_t *p_cdc, uint16_t value, uint16_t index, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t request = p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN] ? PL2303_VENDOR_WRITE_NREQUEST : PL2303_VENDOR_WRITE_REQUEST; - + uint8_t request = p_cdc->pl2303.type == PL2303_TYPE_HXN ? PL2303_VENDOR_WRITE_NREQUEST : PL2303_VENDOR_WRITE_REQUEST; return pl2303_set_request(p_cdc, request, PL2303_VENDOR_WRITE_REQUEST_TYPE, value, index, NULL, 0, complete_cb, user_data); } static inline bool pl2303_supports_hx_status(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint8_t buf = 0; - return pl2303_set_request(p_cdc, PL2303_VENDOR_READ_REQUEST, PL2303_VENDOR_READ_REQUEST_TYPE, PL2303_READ_TYPE_HX_STATUS, 0, &buf, 1, complete_cb, user_data); } @@ -2425,7 +2423,6 @@ static void pl2303_internal_control_complete(tuh_xfer_t *xfer) { static bool pl2303_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_control_cb = complete_cb; TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); - return true; } @@ -2433,7 +2430,6 @@ static bool pl2303_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t comple p_cdc->requested_line_coding.bit_rate = p_cdc->line_coding.bit_rate; p_cdc->user_control_cb = complete_cb; TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); - return true; } @@ -2443,7 +2439,6 @@ static bool pl2303_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits; p_cdc->user_control_cb = complete_cb; TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); - return true; } @@ -2451,7 +2446,6 @@ static bool pl2303_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet // PL2303 has the same bit coding p_cdc->user_control_cb = complete_cb; TU_ASSERT(pl2303_set_control_lines(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); - return true; } @@ -2488,7 +2482,7 @@ static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui TU_VERIFY(p_cdc); p_cdc->serial_drid = SERIAL_DRIVER_PL2303; - p_cdc->pl2303.serial_private.quirks = 0; + p_cdc->pl2303.quirks = 0; p_cdc->pl2303.supports_hx_status = false; tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); @@ -2514,7 +2508,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); // state CONFIG_PL2303_READ1 may have no success due to expected stall by pl2303_supports_hx_status() uint8_t buf = 0; - int8_t type; + pl2303_type_t type; TU_ASSERT(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || state == CONFIG_PL2303_READ1)); switch (state) { @@ -2540,20 +2534,13 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { } type = pl2303_detect_type(p_cdc, 2); // step 2 now with supports_hx_status TU_ASSERT(type != PL2303_TYPE_UNKNOWN); - p_cdc->pl2303.serial_private.type = &pl2303_type_data[type]; - p_cdc->pl2303.serial_private.quirks |= p_cdc->pl2303.serial_private.type->quirks; - #if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL && 0// can be activated if necessary - TU_LOG_P_CDC("bDeviceClass = 0x%02x bMaxPacketSize0 = %u bcdUSB = 0x%04x bcdDevice = 0x%04x", - desc_dev->bDeviceClass, desc_dev->bMaxPacketSize0, - desc_dev->bcdUSB, desc_dev->bcdDevice); - uint16_t vid, pid; - TU_ASSERT(tuh_vid_pid_get(p_cdc->daddr, &vid, &pid)); - TU_LOG_P_CDC("vid = 0x%04x pid = 0x%04x supports_hx_status = %u type = %s quirks = %u", - vid, pid, p_cdc->pl2303.supports_hx_status, - p_cdc->pl2303.serial_private.type->name, p_cdc->pl2303.serial_private.quirks); - #endif + TU_LOG_DRV(" PL2303 type detected: %u\r\n", type); + + p_cdc->pl2303.type = type; + p_cdc->pl2303.quirks |= pl2303_type_data[type].quirks; + // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE1)); break; }// else: continue with next step @@ -2561,7 +2548,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE1: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_write(p_cdc, 0x0404, 0, cdch_process_set_config, CONFIG_PL2303_READ2)); break; }// else: continue with next step @@ -2569,7 +2556,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ2: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_READ3)); break; }// else: continue with next step @@ -2577,7 +2564,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ3: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, cdch_process_set_config, CONFIG_PL2303_READ4)); break; }// else: continue with next step @@ -2585,7 +2572,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ4: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE2)); break; }// else: continue with next step @@ -2593,7 +2580,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE2: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_write(p_cdc, 0x0404, 1, cdch_process_set_config, CONFIG_PL2303_READ5)); break; }// else: continue with next step @@ -2601,7 +2588,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ5: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_READ6)); break; }// else: continue with next step @@ -2609,7 +2596,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_READ6: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE3)); break; }// else: continue with next step @@ -2617,7 +2604,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE3: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_write(p_cdc, 0, 1, cdch_process_set_config, CONFIG_PL2303_WRITE4)); break; }// else: continue with next step @@ -2625,7 +2612,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE4: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_write(p_cdc, 1, 0, cdch_process_set_config, CONFIG_PL2303_WRITE5)); break; }// else: continue with next step @@ -2633,21 +2620,21 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_WRITE5: // purpose unknown, overtaken from Linux Kernel driver - if (p_cdc->pl2303.serial_private.type != &pl2303_type_data[PL2303_TYPE_HXN]) { - uint16_t const windex = (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) ? 0x24 : 0x44; + if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { + uint16_t const windex = (p_cdc->pl2303.quirks & PL2303_QUIRK_LEGACY) ? 0x24 : 0x44; TU_ASSERT(pl2303_vendor_write(p_cdc, 2, windex, cdch_process_set_config, CONFIG_PL2303_RESET_ENDP1)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; - // from here sequence overtaken from Linux Kernel function pl2303_open() + // from here sequence overtaken from Linux Kernel function pl2303_open() case CONFIG_PL2303_RESET_ENDP1: // step 1 - if (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) { + if (p_cdc->pl2303.quirks & PL2303_QUIRK_LEGACY) { TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_OUT_EP, cdch_process_set_config, CONFIG_PL2303_RESET_ENDP2)); } else { /* reset upstream data pipes */ - if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type == PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_write(p_cdc, PL2303_HXN_RESET_REG,// skip CONFIG_PL2303_RESET_ENDP2, no 2nd step PL2303_HXN_RESET_UPSTREAM_PIPE | PL2303_HXN_RESET_DOWNSTREAM_PIPE, cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); @@ -2659,11 +2646,11 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_RESET_ENDP2: // step 2 - if (p_cdc->pl2303.serial_private.quirks & PL2303_QUIRK_LEGACY) { + if (p_cdc->pl2303.quirks & PL2303_QUIRK_LEGACY) { TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_IN_EP, cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); } else { /* reset upstream data pipes */ - if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN]) { + if (p_cdc->pl2303.type == PL2303_TYPE_HXN) { // here nothing to do, only structure of previous step overtaken for better reading and comparison } else { TU_ASSERT(pl2303_vendor_write(p_cdc, 9, 0, cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); @@ -2691,33 +2678,33 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { TU_ATTR_FALLTHROUGH; #endif - // skipped, because it's not working with each PL230x. flow control can be also set by PL2303 EEPROM Writer Program - // case CONFIG_PL2303_FLOW_CTRL_READ: - // // read flow control register for modify & write back in next step - // if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN]) { - // TU_LOG_P_CDC ( "1\r\n" ); - // TU_ASSERT(pl2303_vendor_read(p_cdc, PL2303_HXN_FLOWCTRL_REG, &buf, - // cdch_process_set_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); - // } else { - // TU_LOG_P_CDC ( "2\r\n" ); - // TU_ASSERT(pl2303_vendor_read(p_cdc, 0, &buf, cdch_process_set_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); - // } - // break; - // - // case CONFIG_PL2303_FLOW_CTRL_WRITE: - // // no flow control - // buf = xfer->buffer[0]; - // if (p_cdc->pl2303.serial_private.type == &pl2303_type_data[PL2303_TYPE_HXN]) { - // buf &= (uint8_t) ~PL2303_HXN_FLOWCTRL_MASK; - // buf |= PL2303_HXN_FLOWCTRL_NONE; - // TU_ASSERT(pl2303_vendor_write(p_cdc, PL2303_HXN_FLOWCTRL_REG, buf, - // cdch_process_set_config, CONFIG_PL2303_COMPLETE)); - // } else { - // buf &= (uint8_t) ~PL2303_FLOWCTRL_MASK; - // TU_ASSERT(pl2303_vendor_write(p_cdc, 0, buf, - // cdch_process_set_config, CONFIG_PL2303_COMPLETE)); - // } - // break; + // skipped, because it's not working with each PL230x. flow control can be also set by PL2303 EEPROM Writer Program + // case CONFIG_PL2303_FLOW_CTRL_READ: + // // read flow control register for modify & write back in next step + // if (p_cdc->pl2303.type == PL2303_TYPE_HXN) { + // TU_LOG_P_CDC ( "1\r\n" ); + // TU_ASSERT(pl2303_vendor_read(p_cdc, PL2303_HXN_FLOWCTRL_REG, &buf, + // cdch_process_set_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); + // } else { + // TU_LOG_P_CDC ( "2\r\n" ); + // TU_ASSERT(pl2303_vendor_read(p_cdc, 0, &buf, cdch_process_set_config, CONFIG_PL2303_FLOW_CTRL_WRITE)); + // } + // break; + // + // case CONFIG_PL2303_FLOW_CTRL_WRITE: + // // no flow control + // buf = xfer->buffer[0]; + // if (p_cdc->pl2303.type == PL2303_TYPE_HXN) { + // buf &= (uint8_t) ~PL2303_HXN_FLOWCTRL_MASK; + // buf |= PL2303_HXN_FLOWCTRL_NONE; + // TU_ASSERT(pl2303_vendor_write(p_cdc, PL2303_HXN_FLOWCTRL_REG, buf, + // cdch_process_set_config, CONFIG_PL2303_COMPLETE)); + // } else { + // buf &= (uint8_t) ~PL2303_FLOWCTRL_MASK; + // TU_ASSERT(pl2303_vendor_write(p_cdc, 0, buf, + // cdch_process_set_config, CONFIG_PL2303_COMPLETE)); + // } + // break; case CONFIG_PL2303_COMPLETE: set_config_complete(idx, 0, true); @@ -2732,7 +2719,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { //------------- Helper -------------// -static int8_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step) { +static pl2303_type_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step) { tusb_desc_device_t desc_dev; TU_VERIFY(tuh_descriptor_get_device_local(p_cdc->daddr, &desc_dev), PL2303_TYPE_UNKNOWN); @@ -2932,13 +2919,14 @@ static uint32_t pl2303_encode_baud_rate_divisor_alt(uint8_t buf[PL2303_LINE_CODI static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]) { uint32_t baud = p_cdc->requested_line_coding.bit_rate; uint32_t baud_sup; + const pl2303_type_data_t* type_data = &pl2303_type_data[p_cdc->pl2303.type]; - TU_VERIFY(baud && baud <= p_cdc->pl2303.serial_private.type->max_baud_rate); + TU_VERIFY(baud && baud <= type_data->max_baud_rate); /* * Use direct method for supported baud rates, otherwise use divisors. * Newer chip types do not support divisor encoding. */ - if (p_cdc->pl2303.serial_private.type->no_divisors) { + if (type_data->no_divisors) { baud_sup = baud; } else { baud_sup = pl2303_get_supported_baud_rate(baud); @@ -2946,7 +2934,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_ if (baud == baud_sup) { baud = pl2303_encode_baud_rate_direct(buf, baud); - } else if (p_cdc->pl2303.serial_private.type->alt_divisors) { + } else if (type_data->alt_divisors) { baud = pl2303_encode_baud_rate_divisor_alt(buf, baud); } else { baud = pl2303_encode_baud_rate_divisor(buf, baud); diff --git a/src/class/cdc/serial/pl2303.h b/src/class/cdc/serial/pl2303.h index 40311260d..c01dac0e1 100644 --- a/src/class/cdc/serial/pl2303.h +++ b/src/class/cdc/serial/pl2303.h @@ -97,65 +97,53 @@ // type data typedef enum pl2303_type { - PL2303_TYPE_H, - PL2303_TYPE_HX, - PL2303_TYPE_TA, - PL2303_TYPE_TB, - PL2303_TYPE_HXD, - PL2303_TYPE_HXN, - // PL2303_TYPE_NEED_SUPPORTS_HX_STATUS, - // PL2303_TYPE_UNKNOWN, - PL2303_TYPE_COUNT + PL2303_TYPE_H = 0, // 0 + PL2303_TYPE_HX, // 1 + PL2303_TYPE_TA, // 2 + PL2303_TYPE_TB, // 3 + PL2303_TYPE_HXD, // 4 + PL2303_TYPE_HXN, // 5 + PL2303_TYPE_COUNT, + PL2303_TYPE_NEED_SUPPORTS_HX_STATUS, + PL2303_TYPE_UNKNOWN, } pl2303_type_t; typedef struct pl2303_type_data { - uint8_t const *name; uint32_t const max_baud_rate; - uint8_t const quirks; - uint16_t const no_autoxonxoff:1; - uint16_t const no_divisors:1; - uint16_t const alt_divisors:1; + uint8_t const quirks; + uint8_t const no_autoxonxoff : 1; + uint8_t const no_divisors : 1; + uint8_t const alt_divisors : 1; } pl2303_type_data_t; #define PL2303_TYPE_DATA \ [PL2303_TYPE_H] = { \ - .name = (uint8_t const*)"H", \ .max_baud_rate = 1228800, \ .quirks = PL2303_QUIRK_LEGACY, \ .no_autoxonxoff = true, \ }, \ [PL2303_TYPE_HX] = { \ - .name = (uint8_t const*)"HX", \ .max_baud_rate = 6000000, \ }, \ [PL2303_TYPE_TA] = { \ - .name = (uint8_t const*)"TA", \ .max_baud_rate = 6000000, \ .alt_divisors = true, \ }, \ [PL2303_TYPE_TB] = { \ - .name = (uint8_t const*)"TB", \ .max_baud_rate = 12000000, \ .alt_divisors = true, \ }, \ [PL2303_TYPE_HXD] = { \ - .name = (uint8_t const*)"HXD", \ .max_baud_rate = 12000000, \ }, \ [PL2303_TYPE_HXN] = { \ - .name = (uint8_t const*)"G (HXN)", \ .max_baud_rate = 12000000, \ .no_divisors = true, \ } -// private data types -struct pl2303_serial_private { - const struct pl2303_type_data* type; - uint8_t quirks; -}; - typedef struct TU_ATTR_PACKED { - struct pl2303_serial_private serial_private; + pl2303_type_t type; + uint8_t quirks; bool supports_hx_status; } pl2303_private_t; @@ -167,8 +155,4 @@ typedef struct TU_ATTR_PACKED { #define PL2303_OUT_EP 0x02 #define PL2303_IN_EP 0x83 -// return values of pl2303_detect_type() -#define PL2303_TYPE_NEED_SUPPORTS_HX_STATUS -1 -#define PL2303_TYPE_UNKNOWN -2 - #endif // TUSB_PL2303_H From fa3ec44533ff986688318c3f80e9f373f55318f0 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Jun 2025 17:22:26 +0700 Subject: [PATCH 233/382] revert CFG_TUH_CDC_DTR/RTS_CONTROL_ON_ENUM --- examples/host/cdc_msc_hid/src/tusb_config.h | 5 +- .../cdc_msc_hid_freertos/src/tusb_config.h | 3 +- src/class/cdc/cdc.h | 14 +++--- src/class/cdc/cdc_host.c | 49 ++++++------------- 4 files changed, 24 insertions(+), 47 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 4bd5b0472..e610c5672 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -103,7 +103,7 @@ #define CFG_TUH_ENUMERATION_BUFSIZE 256 #define CFG_TUH_HUB 1 // number of supported hubs -#define CFG_TUH_CDC 1 // number of supported CDC devices. also activates CDC ACM +#define CFG_TUH_CDC 4 // number of supported CDC devices. also activates CDC ACM #define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API @@ -122,8 +122,7 @@ //------------- CDC -------------// // Set Line Control state on enumeration/mounted: -#define CFG_TUH_CDC_DTR_CONTROL_ON_ENUM true -#define CFG_TUH_CDC_RTS_CONTROL_ON_ENUM true +#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM (CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS) // Set Line Coding on enumeration/mounted, value for cdc_line_coding_t // bit rate = 115200, 1 stop bit, no parity, 8 bit data width diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index 94b121672..05deecba0 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -127,8 +127,7 @@ //------------- CDC -------------// // Set Line Control state on enumeration/mounted: -#define CFG_TUH_CDC_DTR_CONTROL_ON_ENUM true -#define CFG_TUH_CDC_RTS_CONTROL_ON_ENUM true +#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM (CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS) // Set Line Coding on enumeration/mounted, value for cdc_line_coding_t // bit rate = 115200, 1 stop bit, no parity, 8 bit data width diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index 10aed79ab..9f3ace63c 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -404,8 +404,7 @@ static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) //--------------------------------------------------------------------+ // Requests //--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint32_t bit_rate; uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space @@ -414,14 +413,13 @@ typedef struct TU_ATTR_PACKED TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); -typedef union TU_ATTR_PACKED -{ +typedef union TU_ATTR_PACKED { struct { - uint8_t dtr : 1; - uint8_t rts : 1; - uint8_t : 6; + uint8_t dtr : 1; + uint8_t rts : 1; + uint8_t : 6; }; - uint8_t all; + uint8_t value; } cdc_line_control_state_t; TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 1, "size is not correct"); diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index dae38ba42..7259e819f 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -52,25 +52,6 @@ serial_drivers[p_cdc->serial_drid].name, ##__VA_ARGS__) #define TU_LOG_P_CDC_BOOL(TXT,VAL) TU_LOG_P_CDC(TXT " " #VAL " = %d", VAL) -// handle line control defines -#if defined(CFG_TUH_CDC_LINE_CONTROL_ON_ENUM) && \ - (defined(CFG_TUH_CDC_DTR_CONTROL_ON_ENUM) || defined(CFG_TUH_CDC_RTS_CONTROL_ON_ENUM)) - TU_VERIFY_STATIC(false, "Contradictory line control defines"); -#endif - -#ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - #define LINE_CONTROL_ON_ENUM CFG_TUH_CDC_LINE_CONTROL_ON_ENUM -#elif defined(CFG_TUH_CDC_DTR_CONTROL_ON_ENUM) || defined(CFG_TUH_CDC_RTS_CONTROL_ON_ENUM) - #ifndef CFG_TUH_CDC_DTR_CONTROL_ON_ENUM - #define CFG_TUH_CDC_DTR_CONTROL_ON_ENUM 0 - #endif - #ifndef CFG_TUH_CDC_RTS_CONTROL_ON_ENUM - #define CFG_TUH_CDC_RTS_CONTROL_ON_ENUM 0 - #endif - #define LINE_CONTROL_ON_ENUM ( ( CFG_TUH_CDC_DTR_CONTROL_ON_ENUM ? CDC_CONTROL_LINE_STATE_DTR : 0 ) | \ - ( CFG_TUH_CDC_RTS_CONTROL_ON_ENUM ? CDC_CONTROL_LINE_STATE_RTS : 0 ) ) -#endif - //--------------------------------------------------------------------+ // Host CDC Interface //--------------------------------------------------------------------+ @@ -396,7 +377,7 @@ static cdch_interface_t * make_new_itf(uint8_t daddr, tusb_desc_interface_t cons p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass; p_cdc->bInterfaceProtocol = itf_desc->bInterfaceProtocol; p_cdc->line_coding = (cdc_line_coding_t) { 0, 0, 0, 0 }; - p_cdc->line_state.all = 0; + p_cdc->line_state.value = 0; return p_cdc; } } @@ -661,7 +642,7 @@ bool tuh_cdc_set_control_line_state_u(uint8_t idx, cdc_line_control_state_t line bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // uses uint16_t for line_state => DTR (bit 0), RTS (bit 1) - return tuh_cdc_set_control_line_state_u(idx, (cdc_line_control_state_t) { .all = (uint8_t) line_state }, + return tuh_cdc_set_control_line_state_u(idx, (cdc_line_control_state_t) { .value = (uint8_t) line_state }, complete_cb, user_data); } @@ -1004,7 +985,7 @@ static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t co .direction = TUSB_DIR_OUT }, .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = tu_htole16((uint16_t) p_cdc->requested_line_state.all), + .wValue = tu_htole16((uint16_t) p_cdc->requested_line_state.value), .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), .wLength = 0 }; @@ -1137,9 +1118,9 @@ static bool acm_process_set_config(tuh_xfer_t *xfer) { switch (state) { case CONFIG_ACM_SET_CONTROL_LINE_STATE: - #ifdef LINE_CONTROL_ON_ENUM + #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM if (p_cdc->acm_capability.support_line_request) { - p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; + p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT(acm_set_control_line_state(p_cdc, cdch_process_set_config, CONFIG_ACM_SET_LINE_CODING)); break; } @@ -1426,8 +1407,8 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { break; case CONFIG_FTDI_MODEM_CTRL: - #ifdef LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; + #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; p_cdc->user_control_cb = cdch_process_set_config; TU_ASSERT(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_COMPLETE)); break; @@ -1735,7 +1716,7 @@ static inline bool cp210x_set_mhs(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet // CP210x has the same bit coding return cp210x_set_request(p_cdc, CP210X_SET_MHS, (uint16_t) (CP210X_CONTROL_WRITE_DTR | CP210X_CONTROL_WRITE_RTS | - p_cdc->requested_line_state.all), + p_cdc->requested_line_state.value), NULL, 0, complete_cb, user_data); } @@ -1873,8 +1854,8 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) { #endif case CONFIG_CP210X_SET_DTR_RTS: - #ifdef LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; + #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; p_cdc->user_control_cb = cdch_process_set_config; TU_ASSERT(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_COMPLETE)); break; @@ -2153,8 +2134,8 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { break; case CONFIG_CH34X_MODEM_CONTROL: - #ifdef LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; + #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; p_cdc->user_control_cb = cdch_process_set_config; TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE)); break; @@ -2332,7 +2313,7 @@ static inline bool pl2303_supports_hx_status(cdch_interface_t *p_cdc, tuh_xfer_c static inline bool pl2303_set_control_lines(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // PL2303 has the same bit coding return pl2303_set_request(p_cdc, PL2303_SET_CONTROL_REQUEST, PL2303_SET_CONTROL_REQUEST_TYPE, - p_cdc->requested_line_state.all, 0, NULL, 0, complete_cb, user_data); + p_cdc->requested_line_state.value, 0, NULL, 0, complete_cb, user_data); } //static bool pl2303_get_line_request(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BUFSIZE]) @@ -2670,8 +2651,8 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { #endif case CONFIG_PL2303_MODEM_CONTROL: - #ifdef LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.all = LINE_CONTROL_ON_ENUM; + #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_COMPLETE)); break; #else From ce9140a150f685ae228362c5fcd0b85a7900e67a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Jun 2025 17:57:21 +0700 Subject: [PATCH 234/382] rename tuh_cdc_get_local_line_coding to tuh_cdc_get_line_coding_local add tuh_cdc_get_control_line_state_local() implement tuh_cdc_get/set_dtr/rts() as inline --- src/class/cdc/cdc_host.c | 55 +++++++--------------------------------- src/class/cdc/cdc_host.h | 45 ++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 57 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 7259e819f..80b01f928 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -427,27 +427,14 @@ bool tuh_cdc_mounted(uint8_t idx) { return p_cdc->mounted; } -bool tuh_cdc_get_dtr(uint8_t idx) { +bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t* line_state) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - - bool ret = p_cdc->line_state.dtr; -// TU_LOG_P_CDC_BOOL("get DTR", ret); - - return ret; + *line_state = p_cdc->line_state.value; + return true; } -bool tuh_cdc_get_rts(uint8_t idx) { - cdch_interface_t * p_cdc = get_itf(idx); - TU_VERIFY(p_cdc); - - bool ret = p_cdc->line_state.rts; -// TU_LOG_P_CDC_BOOL("get RTS", ret); - - return ret; -} - -bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t * line_coding) { +bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t * line_coding) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); @@ -622,46 +609,22 @@ static bool set_function_call ( } } -bool tuh_cdc_set_control_line_state_u(uint8_t idx, cdc_line_control_state_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - // uses cdc_line_control_state_t union for line_state +bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set control line state dtr = %u rts = %u", line_state.dtr, line_state.rts); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; - p_cdc->requested_line_state = line_state; + p_cdc->requested_line_state.value = (uint8_t) line_state; + TU_LOG_P_CDC("set control line state dtr = %u rts = %u", p_cdc->requested_line_state.dtr, p_cdc->requested_line_state.rts); - bool ret = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data); + const bool ret = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data); if (ret && !complete_cb) { - p_cdc->line_state = line_state; + p_cdc->line_state = p_cdc->requested_line_state; } return ret; } -bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - // uses uint16_t for line_state => DTR (bit 0), RTS (bit 1) - - return tuh_cdc_set_control_line_state_u(idx, (cdc_line_control_state_t) { .value = (uint8_t) line_state }, - complete_cb, user_data); -} - -bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t * p_cdc = get_itf(idx); - TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - cdc_line_control_state_t const line_state = { .dtr = dtr_state, .rts = p_cdc->line_state.rts }; - - return tuh_cdc_set_control_line_state_u(idx, line_state, complete_cb, user_data); -} - -bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdch_interface_t *p_cdc = get_itf(idx); - TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - cdc_line_control_state_t const line_state = {.rts = rts_state, .dtr = p_cdc->line_state.dtr}; - - return tuh_cdc_set_control_line_state_u(idx, line_state, complete_cb, user_data); -} - bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 63eb1fc0f..688164cb2 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -69,14 +69,27 @@ uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num); // return true if index is correct and interface is currently mounted bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info); -// Check if a interface is mounted +// Check if an interface is mounted bool tuh_cdc_mounted(uint8_t idx); +// Get local (cached) line state +// This function should return correct values if tuh_cdc_set_control_line_state() / tuh_cdc_get_control_line_state() +// are invoked previously or CFG_TUH_CDC_LINE_STATE_ON_ENUM is defined. +bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t* line_state); + // Get current DTR status -bool tuh_cdc_get_dtr(uint8_t idx); +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_get_dtr(uint8_t idx) { + uint16_t line_state; + TU_VERIFY(tuh_cdc_get_control_line_state_local(idx, &line_state)); + return (line_state & CDC_CONTROL_LINE_STATE_DTR) != 0; +} // Get current RTS status -bool tuh_cdc_get_rts(uint8_t idx); +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_get_rts(uint8_t idx) { + uint16_t line_state; + TU_VERIFY(tuh_cdc_get_control_line_state_local(idx, &line_state)); + return (line_state & CDC_CONTROL_LINE_STATE_RTS) != 0; +} // Check if interface is connected (DTR active) TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx) { @@ -87,7 +100,9 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx) { // This function should return correct values if tuh_cdc_set_line_coding() / tuh_cdc_get_line_coding() // are invoked previously or CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined. // NOTE: This function does not make any USB transfer request to device. -bool tuh_cdc_get_local_line_coding(uint8_t idx, cdc_line_coding_t* line_coding); +bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t* line_coding); + +#define tuh_cdc_get_local_line_coding tuh_cdc_get_line_coding_local // backward compatibility //--------------------------------------------------------------------+ // Write API @@ -131,14 +146,22 @@ bool tuh_cdc_read_clear (uint8_t idx); // - The function will return true if transfer is successful, false otherwise. //--------------------------------------------------------------------+ -// Request to Set Control Line State -bool tuh_cdc_set_control_line_state_u(uint8_t idx, cdc_line_control_state_t line_state, // uses cdc_line_control_state_t union for line_state - tuh_xfer_cb_t complete_cb, uintptr_t user_data); -bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, // uses uint16_t for line_state (legacy function) - tuh_xfer_cb_t complete_cb, uintptr_t user_data); // DTR (bit 0), RTS (bit 1) +// Request to Set Control Line State: DTR (bit 0), RTS (bit 1) +bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set DTR -bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set RTS +// Request to Set DTR +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + cdc_line_control_state_t line_state = { .dtr = dtr_state }; + line_state.rts = tuh_cdc_get_rts(idx); + return tuh_cdc_set_control_line_state(idx, line_state.value, complete_cb, user_data); +} + +// Request to Set RTS +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + cdc_line_control_state_t line_state = { .rts = rts_state }; + line_state.dtr = tuh_cdc_get_dtr(idx); + return tuh_cdc_set_control_line_state(idx, line_state.value, complete_cb, user_data); +} // Request to set baudrate bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); From 221b5288e43feff140c695af4481b7815f1b56cd Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 19 Jun 2025 18:14:24 +0700 Subject: [PATCH 235/382] union ftdi/pl2303/acm data to save memory. --- src/class/cdc/cdc_host.c | 283 ++++++++++++++++++++------------------- 1 file changed, 143 insertions(+), 140 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 80b01f928..2fe2c85bc 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -65,27 +65,30 @@ typedef struct { uint8_t ep_notif; uint8_t serial_drid; // Serial Driver ID bool mounted; // Enumeration is complete - cdc_acm_capability_t acm_capability; - TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; // Baudrate, stop bits, parity, data width - TU_ATTR_ALIGNED(4) cdc_line_coding_t requested_line_coding; - // 1 byte padding + struct { + TU_ATTR_ALIGNED(4) cdc_line_coding_t coding; // Baudrate, stop bits, parity, data width + cdc_line_control_state_t control_state; // DTR, RTS + } line, requested_line; - cdc_line_control_state_t line_state; - cdc_line_control_state_t requested_line_state; - - tuh_xfer_cb_t user_control_cb; + tuh_xfer_cb_t user_complete_cb; // required since we handle request internally first #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X tuh_xfer_cb_t requested_complete_cb; #endif - #if CFG_TUH_CDC_FTDI - ftdi_private_t ftdi; - #endif + union { + struct { + cdc_acm_capability_t capability; + } acm; - #if CFG_TUH_CDC_PL2303 + #if CFG_TUH_CDC_FTDI + ftdi_private_t ftdi; + #endif + + #if CFG_TUH_CDC_PL2303 pl2303_private_t pl2303; - #endif + #endif + }; struct { tu_edpt_stream_t tx; @@ -376,8 +379,8 @@ static cdch_interface_t * make_new_itf(uint8_t daddr, tusb_desc_interface_t cons p_cdc->bInterfaceNumber = itf_desc->bInterfaceNumber; p_cdc->bInterfaceSubClass = itf_desc->bInterfaceSubClass; p_cdc->bInterfaceProtocol = itf_desc->bInterfaceProtocol; - p_cdc->line_coding = (cdc_line_coding_t) { 0, 0, 0, 0 }; - p_cdc->line_state.value = 0; + p_cdc->line.coding = (cdc_line_coding_t) { 0, 0, 0, 0 }; + p_cdc->line.control_state.value = 0; return p_cdc; } } @@ -430,7 +433,7 @@ bool tuh_cdc_mounted(uint8_t idx) { bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t* line_state) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - *line_state = p_cdc->line_state.value; + *line_state = p_cdc->line.control_state.value; return true; } @@ -438,10 +441,10 @@ bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t * line_coding) cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - *line_coding = p_cdc->line_coding; + *line_coding = p_cdc->line.coding; TU_LOG_P_CDC("get line coding %lu %u%c%s", - p_cdc->line_coding.bit_rate, p_cdc->line_coding.data_bits, - CDC_LINE_CODING_PARITY_CHAR(p_cdc->line_coding.parity), + p_cdc->line.coding.bit_rate, p_cdc->line.coding.data_bits, + CDC_LINE_CODING_PARITY_CHAR(p_cdc->line.coding.parity), CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); return true; @@ -533,7 +536,7 @@ static bool set_line_coding_sequence( // non-blocking // stage 1 set baudrate p_cdc->requested_complete_cb = complete_cb; // store complete_cb to be used in set_line_coding_stage1_complete() - p_cdc->user_control_cb = set_line_coding_stage1_complete; + p_cdc->user_complete_cb = set_line_coding_stage1_complete; return set_baudrate_request(p_cdc, internal_control_complete, user_data); } else { // blocking sequence @@ -549,7 +552,7 @@ static bool set_line_coding_sequence( TU_VERIFY(result == XFER_RESULT_SUCCESS); // overtake baudrate after successful request - p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; // stage 2 set data format result = XFER_RESULT_INVALID; @@ -577,7 +580,7 @@ static void set_line_coding_stage1_complete( if (xfer->result == XFER_RESULT_SUCCESS) { // stage 1 success, continue with stage 2 - p_cdc->user_control_cb = p_cdc->requested_complete_cb; + p_cdc->user_complete_cb = p_cdc->requested_complete_cb; set_data_format_request(p_cdc, internal_control_complete, xfer->user_data); } else { // stage 1 failed, notify user @@ -614,13 +617,13 @@ bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_c TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; - p_cdc->requested_line_state.value = (uint8_t) line_state; - TU_LOG_P_CDC("set control line state dtr = %u rts = %u", p_cdc->requested_line_state.dtr, p_cdc->requested_line_state.rts); + p_cdc->requested_line.control_state.value = (uint8_t) line_state; + TU_LOG_P_CDC("set control line state dtr = %u rts = %u", p_cdc->requested_line.control_state.dtr, p_cdc->requested_line.control_state.rts); const bool ret = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data); if (ret && !complete_cb) { - p_cdc->line_state = p_cdc->requested_line_state; + p_cdc->line.control_state = p_cdc->requested_line.control_state; } return ret; } @@ -631,12 +634,12 @@ bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete TU_LOG_P_CDC("set baudrate %lu", baudrate); cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; - p_cdc->requested_line_coding.bit_rate = baudrate; + p_cdc->requested_line.coding.bit_rate = baudrate; bool ret = set_function_call(p_cdc, driver->set_baudrate, complete_cb, user_data); if (ret && !complete_cb) { - p_cdc->line_coding.bit_rate = baudrate; + p_cdc->line.coding.bit_rate = baudrate; } // TU_LOG_P_CDC_BOOL("set baudrate", ret); @@ -652,16 +655,16 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin CDC_LINE_CODING_STOP_BITS_TEXT(stop_bits)); cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; - p_cdc->requested_line_coding.stop_bits = stop_bits; - p_cdc->requested_line_coding.parity = parity; - p_cdc->requested_line_coding.data_bits = data_bits; + p_cdc->requested_line.coding.stop_bits = stop_bits; + p_cdc->requested_line.coding.parity = parity; + p_cdc->requested_line.coding.data_bits = data_bits; bool ret = set_function_call(p_cdc, driver->set_data_format, complete_cb, user_data); if (ret && !complete_cb) { - p_cdc->line_coding.stop_bits = stop_bits; - p_cdc->line_coding.parity = parity; - p_cdc->line_coding.data_bits = data_bits; + p_cdc->line.coding.stop_bits = stop_bits; + p_cdc->line.coding.parity = parity; + p_cdc->line.coding.data_bits = data_bits; } // TU_LOG_P_CDC_BOOL("set data format", ret); @@ -678,12 +681,12 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; - p_cdc->requested_line_coding = *line_coding; + p_cdc->requested_line.coding = *line_coding; bool ret = set_function_call(p_cdc, driver->set_line_coding, complete_cb, user_data); if (ret && !complete_cb) { - p_cdc->line_coding = *line_coding; + p_cdc->line.coding = *line_coding; } // TU_LOG_P_CDC_BOOL("set line coding", ret); @@ -921,25 +924,25 @@ static void acm_internal_control_complete(tuh_xfer_t *xfer) { if (success) { switch (xfer->setup->bRequest) { case CDC_REQUEST_SET_CONTROL_LINE_STATE: - p_cdc->line_state = p_cdc->requested_line_state; + p_cdc->line.control_state = p_cdc->requested_line.control_state; break; case CDC_REQUEST_SET_LINE_CODING: - p_cdc->line_coding = p_cdc->requested_line_coding; + p_cdc->line.coding = p_cdc->requested_line.coding; break; default: break; } } - xfer->complete_cb = p_cdc->user_control_cb; + xfer->complete_cb = p_cdc->user_complete_cb; if (xfer->complete_cb) { xfer->complete_cb(xfer); } } static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm_capability.support_line_request); + TU_VERIFY(p_cdc->acm.capability.support_line_request); tusb_control_request_t const request = { .bmRequestType_bit = { @@ -948,12 +951,12 @@ static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t co .direction = TUSB_DIR_OUT }, .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE, - .wValue = tu_htole16((uint16_t) p_cdc->requested_line_state.value), + .wValue = tu_htole16((uint16_t) p_cdc->requested_line.control_state.value), .wIndex = tu_htole16((uint16_t) p_cdc->bInterfaceNumber), .wLength = 0 }; - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; tuh_xfer_t xfer = { .daddr = p_cdc->daddr, @@ -970,9 +973,9 @@ static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t co } static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm_capability.support_line_request); - TU_VERIFY((p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8) || - p_cdc->requested_line_coding.data_bits == 16); + TU_VERIFY(p_cdc->acm.capability.support_line_request); + TU_VERIFY((p_cdc->requested_line.coding.data_bits >= 5 && p_cdc->requested_line.coding.data_bits <= 8) || + p_cdc->requested_line.coding.data_bits == 16); tusb_control_request_t const request = { .bmRequestType_bit = { @@ -988,9 +991,9 @@ static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ // use usbh enum buf to hold line coding since user line_coding variable does not live long enough uint8_t *enum_buf = usbh_get_enum_buf(); - memcpy(enum_buf, &p_cdc->requested_line_coding, sizeof(cdc_line_coding_t)); + memcpy(enum_buf, &p_cdc->requested_line.coding, sizeof(cdc_line_coding_t)); - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; tuh_xfer_t xfer = { .daddr = p_cdc->daddr, @@ -1007,15 +1010,15 @@ static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ } static bool acm_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->requested_line_coding.bit_rate = p_cdc->line_coding.bit_rate; + p_cdc->requested_line.coding.bit_rate = p_cdc->line.coding.bit_rate; return acm_set_line_coding(p_cdc, complete_cb, user_data); } static bool acm_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->requested_line_coding.stop_bits = p_cdc->line_coding.stop_bits; - p_cdc->requested_line_coding.parity = p_cdc->line_coding.parity; - p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits; + p_cdc->requested_line.coding.stop_bits = p_cdc->line.coding.stop_bits; + p_cdc->requested_line.coding.parity = p_cdc->line.coding.parity; + p_cdc->requested_line.coding.data_bits = p_cdc->line.coding.data_bits; return acm_set_line_coding(p_cdc, complete_cb, user_data); } @@ -1042,7 +1045,7 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint1 while ((p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) { if (CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc)) { // save ACM bmCapabilities - p_cdc->acm_capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; + p_cdc->acm.capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; } p_desc = tu_desc_next(p_desc); @@ -1082,8 +1085,8 @@ static bool acm_process_set_config(tuh_xfer_t *xfer) { switch (state) { case CONFIG_ACM_SET_CONTROL_LINE_STATE: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - if (p_cdc->acm_capability.support_line_request) { - p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + if (p_cdc->acm.capability.support_line_request) { + p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT(acm_set_control_line_state(p_cdc, cdch_process_set_config, CONFIG_ACM_SET_LINE_CODING)); break; } @@ -1092,8 +1095,8 @@ static bool acm_process_set_config(tuh_xfer_t *xfer) { case CONFIG_ACM_SET_LINE_CODING: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - if (p_cdc->acm_capability.support_line_request) { - p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + if (p_cdc->acm.capability.support_line_request) { + p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; TU_ASSERT(acm_set_line_coding(p_cdc, cdch_process_set_config, CONFIG_ACM_COMPLETE)); break; } @@ -1175,10 +1178,10 @@ static bool ftdi_change_speed(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb } static bool ftdi_set_data_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 7 && p_cdc->requested_line_coding.data_bits <= 8, 0); - uint16_t value = (uint16_t) ((p_cdc->requested_line_coding.data_bits & 0xfUL) | // data bit quantity is stored in bits 0-3 - (p_cdc->requested_line_coding.parity & 0x7UL) << 8 | // parity is stored in bits 8-10, same coding - (p_cdc->requested_line_coding.stop_bits & 0x3UL) << 11); // stop bits quantity is stored in bits 11-12, same coding + TU_VERIFY(p_cdc->requested_line.coding.data_bits >= 7 && p_cdc->requested_line.coding.data_bits <= 8, 0); + uint16_t value = (uint16_t) ((p_cdc->requested_line.coding.data_bits & 0xfUL) | // data bit quantity is stored in bits 0-3 + (p_cdc->requested_line.coding.parity & 0x7UL) << 8 | // parity is stored in bits 8-10, same coding + (p_cdc->requested_line.coding.stop_bits & 0x3UL) << 11); // stop bits quantity is stored in bits 11-12, same coding // not each FTDI supports 1.5 stop bits return ftdi_set_request(p_cdc, FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, @@ -1186,8 +1189,8 @@ static bool ftdi_set_data_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet } static inline bool ftdi_update_mctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint16_t value = (uint16_t) ((p_cdc->requested_line_state.dtr ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW) | - (p_cdc->requested_line_state.rts ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW)); + uint16_t value = (uint16_t) ((p_cdc->requested_line.control_state.dtr ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW) | + (p_cdc->requested_line.control_state.rts ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW)); return ftdi_set_request(p_cdc, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, value, p_cdc->ftdi.channel, complete_cb, user_data); @@ -1206,35 +1209,35 @@ static void ftdi_internal_control_complete(tuh_xfer_t *xfer) { if (success) { if (xfer->setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST && xfer->setup->bmRequestType == FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE ) { - p_cdc->line_state = p_cdc->requested_line_state; + p_cdc->line.control_state = p_cdc->requested_line.control_state; } if (xfer->setup->bRequest == FTDI_SIO_SET_DATA_REQUEST && xfer->setup->bmRequestType == FTDI_SIO_SET_DATA_REQUEST_TYPE ) { - p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; - p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; - p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; + p_cdc->line.coding.stop_bits = p_cdc->requested_line.coding.stop_bits; + p_cdc->line.coding.parity = p_cdc->requested_line.coding.parity; + p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits; } if (xfer->setup->bRequest == FTDI_SIO_SET_BAUDRATE_REQUEST && xfer->setup->bmRequestType == FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE ) { - p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; } } - xfer->complete_cb = p_cdc->user_control_cb; + xfer->complete_cb = p_cdc->user_complete_cb; if (xfer->complete_cb) { xfer->complete_cb(xfer); } } static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(ftdi_set_data_request(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); return true; } static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(ftdi_change_speed(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); return true; @@ -1261,7 +1264,7 @@ static bool ftdi_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complet } static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(ftdi_update_mctrl(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); return true; @@ -1339,15 +1342,15 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { // from here sequence overtaken from Linux Kernel function ftdi_open() case CONFIG_FTDI_SIO_RESET: - p_cdc->user_control_cb = cdch_process_set_config; + p_cdc->user_complete_cb = cdch_process_set_config; TU_ASSERT(ftdi_sio_reset(p_cdc, cdch_process_set_config, CONFIG_FTDI_SET_DATA)); break; // from here sequence overtaken from Linux Kernel function ftdi_set_termios() case CONFIG_FTDI_SET_DATA: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - p_cdc->user_control_cb = cdch_process_set_config; + p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + p_cdc->user_complete_cb = cdch_process_set_config; TU_ASSERT(ftdi_set_data_request(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_SET_BAUDRATE)); break; #else @@ -1356,7 +1359,7 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { case CONFIG_FTDI_SET_BAUDRATE: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->user_control_cb = cdch_process_set_config; + p_cdc->user_complete_cb = cdch_process_set_config; TU_ASSERT(ftdi_change_speed(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_FLOW_CONTROL)); break; #else @@ -1371,8 +1374,8 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { case CONFIG_FTDI_MODEM_CTRL: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - p_cdc->user_control_cb = cdch_process_set_config; + p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + p_cdc->user_complete_cb = cdch_process_set_config; TU_ASSERT(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_COMPLETE)); break; #else @@ -1529,7 +1532,7 @@ static inline uint32_t ftdi_2232h_baud_to_divisor(uint32_t baud) { } static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { - uint32_t baud = p_cdc->requested_line_coding.bit_rate; + uint32_t baud = p_cdc->requested_line.coding.bit_rate; uint32_t div_value = 0; TU_VERIFY(baud); @@ -1661,16 +1664,16 @@ static inline bool cp210x_ifc_enable(cdch_interface_t *p_cdc, uint16_t enabled, static bool cp210x_set_baudrate_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // Not every baud rate is supported. See datasheets and AN205 "CP210x Baud Rate Support" - uint32_t baud_le = tu_htole32(p_cdc->requested_line_coding.bit_rate); + uint32_t baud_le = tu_htole32(p_cdc->requested_line.coding.bit_rate); return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, complete_cb, user_data); } static bool cp210x_set_line_ctl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8, 0); - uint16_t lcr = (uint16_t) ((p_cdc->requested_line_coding.data_bits & 0xfUL) << 8 | // data bit quantity is stored in bits 8-11 - (p_cdc->requested_line_coding.parity & 0xfUL) << 4 | // parity is stored in bits 4-7, same coding - (p_cdc->requested_line_coding.stop_bits & 0xfUL)); // parity is stored in bits 0-3, same coding + TU_VERIFY(p_cdc->requested_line.coding.data_bits >= 5 && p_cdc->requested_line.coding.data_bits <= 8, 0); + uint16_t lcr = (uint16_t) ((p_cdc->requested_line.coding.data_bits & 0xfUL) << 8 | // data bit quantity is stored in bits 8-11 + (p_cdc->requested_line.coding.parity & 0xfUL) << 4 | // parity is stored in bits 4-7, same coding + (p_cdc->requested_line.coding.stop_bits & 0xfUL)); // parity is stored in bits 0-3, same coding return cp210x_set_request(p_cdc, CP210X_SET_LINE_CTL, lcr, NULL, 0, complete_cb, user_data); } @@ -1679,7 +1682,7 @@ static inline bool cp210x_set_mhs(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet // CP210x has the same bit coding return cp210x_set_request(p_cdc, CP210X_SET_MHS, (uint16_t) (CP210X_CONTROL_WRITE_DTR | CP210X_CONTROL_WRITE_RTS | - p_cdc->requested_line_state.value), + p_cdc->requested_line.control_state.value), NULL, 0, complete_cb, user_data); } @@ -1697,38 +1700,38 @@ static void cp210x_internal_control_complete(tuh_xfer_t *xfer) { if (success) { switch (xfer->setup->bRequest) { case CP210X_SET_MHS: - p_cdc->line_state = p_cdc->requested_line_state; + p_cdc->line.control_state = p_cdc->requested_line.control_state; break; case CP210X_SET_LINE_CTL: - p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; - p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; - p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; + p_cdc->line.coding.stop_bits = p_cdc->requested_line.coding.stop_bits; + p_cdc->line.coding.parity = p_cdc->requested_line.coding.parity; + p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits; break; case CP210X_SET_BAUDRATE: - p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; break; default: break; } } - xfer->complete_cb = p_cdc->user_control_cb; + xfer->complete_cb = p_cdc->user_complete_cb; if (xfer->complete_cb) { xfer->complete_cb(xfer); } } static bool cp210x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(cp210x_set_baudrate_request(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); return true; } static bool cp210x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(cp210x_set_line_ctl(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); return true; @@ -1752,7 +1755,7 @@ static bool cp210x_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t comple } static bool cp210x_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(cp210x_set_mhs(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); return true; @@ -1799,8 +1802,8 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) { case CONFIG_CP210X_SET_BAUDRATE_REQUEST: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - p_cdc->user_control_cb = cdch_process_set_config; + p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + p_cdc->user_complete_cb = cdch_process_set_config; TU_ASSERT(cp210x_set_baudrate_request(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_SET_LINE_CTL)); break; #else @@ -1809,7 +1812,7 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) { case CONFIG_CP210X_SET_LINE_CTL: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->user_control_cb = cdch_process_set_config; + p_cdc->user_complete_cb = cdch_process_set_config; TU_ASSERT(cp210x_set_line_ctl(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_SET_DTR_RTS)); break; #else @@ -1818,8 +1821,8 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) { case CONFIG_CP210X_SET_DTR_RTS: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - p_cdc->user_control_cb = cdch_process_set_config; + p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + p_cdc->user_complete_cb = cdch_process_set_config; TU_ASSERT(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_COMPLETE)); break; #else @@ -1923,8 +1926,8 @@ static bool ch34x_write_reg_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t comp static bool ch34x_modem_ctrl_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // CH34x signals are inverted - uint8_t control = ~((p_cdc->requested_line_state.rts ? CH34X_BIT_RTS : 0) | - (p_cdc->requested_line_state.dtr ? CH34X_BIT_DTR : 0)); + uint8_t control = ~((p_cdc->requested_line.control_state.rts ? CH34X_BIT_RTS : 0) | + (p_cdc->requested_line.control_state.dtr ? CH34X_BIT_DTR : 0)); return ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, complete_cb, user_data); } @@ -1947,14 +1950,14 @@ static void ch34x_internal_control_complete(tuh_xfer_t *xfer) { switch (tu_le16toh(xfer->setup->wValue)) { case CH34X_REG16_DIVISOR_PRESCALER: // baudrate - p_cdc->line_coding.bit_rate = p_cdc->requested_line_coding.bit_rate; + p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; break; case CH32X_REG16_LCR2_LCR: // data format - p_cdc->line_coding.stop_bits = p_cdc->requested_line_coding.stop_bits; - p_cdc->line_coding.parity = p_cdc->requested_line_coding.parity; - p_cdc->line_coding.data_bits = p_cdc->requested_line_coding.data_bits; + p_cdc->line.coding.stop_bits = p_cdc->requested_line.coding.stop_bits; + p_cdc->line.coding.parity = p_cdc->requested_line.coding.parity; + p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits; break; default: break; @@ -1962,28 +1965,28 @@ static void ch34x_internal_control_complete(tuh_xfer_t *xfer) { break; case CH34X_REQ_MODEM_CTRL: - p_cdc->line_state = p_cdc->requested_line_state; + p_cdc->line.control_state = p_cdc->requested_line.control_state; break; default: break; } } - xfer->complete_cb = p_cdc->user_control_cb; + xfer->complete_cb = p_cdc->user_complete_cb; if (xfer->complete_cb) { xfer->complete_cb(xfer); } } static bool ch34x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(ch34x_write_reg_data_format(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); return true; } static bool ch34x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); return true; @@ -2008,7 +2011,7 @@ static bool ch34x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t comple } static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); return true; @@ -2073,7 +2076,7 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { // see drivers from WCH vendor, Linux kernel and FreeBSD if (version >= 0x30) { // init CH34x with line coding - p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; + p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc); uint8_t const lcr = ch34x_get_lcr(p_cdc); TU_ASSERT(div_ps != 0 && lcr != 0); @@ -2085,7 +2088,7 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { case CONFIG_CH34X_SPECIAL_REG_WRITE: // overtake line coding and do special reg write, purpose unknown, overtaken from WCH driver - p_cdc->line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; + p_cdc->line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X; TU_ASSERT(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x0F, CH341_REG_0x2C), 0x0007, cdch_process_set_config, CONFIG_CH34X_FLOW_CONTROL)); break; @@ -2098,8 +2101,8 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { case CONFIG_CH34X_MODEM_CONTROL: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - p_cdc->user_control_cb = cdch_process_set_config; + p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + p_cdc->user_complete_cb = cdch_process_set_config; TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE)); break; #else @@ -2121,7 +2124,7 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { // calculate divisor and prescaler for baudrate, return it as 16-bit combined value static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t *p_cdc) { - uint32_t const baval = p_cdc->requested_line_coding.bit_rate; + uint32_t const baval = p_cdc->requested_line.coding.bit_rate; uint8_t a; uint8_t b; uint32_t c; @@ -2171,9 +2174,9 @@ static uint16_t ch34x_get_divisor_prescaler(cdch_interface_t *p_cdc) { // calculate lcr value from data coding static uint8_t ch34x_get_lcr(cdch_interface_t *p_cdc) { - uint8_t const stop_bits = p_cdc->requested_line_coding.stop_bits; - uint8_t const parity = p_cdc->requested_line_coding.parity; - uint8_t const data_bits = p_cdc->requested_line_coding.data_bits; + uint8_t const stop_bits = p_cdc->requested_line.coding.stop_bits; + uint8_t const parity = p_cdc->requested_line.coding.parity; + uint8_t const data_bits = p_cdc->requested_line.coding.data_bits; uint8_t lcr = CH34X_LCR_ENABLE_RX | CH34X_LCR_ENABLE_TX; TU_VERIFY(data_bits >= 5 && data_bits <= 8); @@ -2276,7 +2279,7 @@ static inline bool pl2303_supports_hx_status(cdch_interface_t *p_cdc, tuh_xfer_c static inline bool pl2303_set_control_lines(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // PL2303 has the same bit coding return pl2303_set_request(p_cdc, PL2303_SET_CONTROL_REQUEST, PL2303_SET_CONTROL_REQUEST_TYPE, - p_cdc->requested_line_state.value, 0, NULL, 0, complete_cb, user_data); + p_cdc->requested_line.control_state.value, 0, NULL, 0, complete_cb, user_data); } //static bool pl2303_get_line_request(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BUFSIZE]) @@ -2292,14 +2295,14 @@ static bool pl2303_set_line_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t compl * even to the same values as before. Thus we actually need to filter * in this specific case. */ - TU_VERIFY(p_cdc->requested_line_coding.data_bits != p_cdc->line_coding.data_bits || - p_cdc->requested_line_coding.stop_bits != p_cdc->line_coding.stop_bits || - p_cdc->requested_line_coding.parity != p_cdc->line_coding.parity || - p_cdc->requested_line_coding.bit_rate != p_cdc->line_coding.bit_rate ); + TU_VERIFY(p_cdc->requested_line.coding.data_bits != p_cdc->line.coding.data_bits || + p_cdc->requested_line.coding.stop_bits != p_cdc->line.coding.stop_bits || + p_cdc->requested_line.coding.parity != p_cdc->line.coding.parity || + p_cdc->requested_line.coding.bit_rate != p_cdc->line.coding.bit_rate ); /* For reference buf[6] data bits value */ - TU_VERIFY(p_cdc->requested_line_coding.data_bits >= 5 && p_cdc->requested_line_coding.data_bits <= 8, 0); - buf[6] = p_cdc->requested_line_coding.data_bits; + TU_VERIFY(p_cdc->requested_line.coding.data_bits >= 5 && p_cdc->requested_line.coding.data_bits <= 8, 0); + buf[6] = p_cdc->requested_line.coding.data_bits; /* For reference buf[0]:buf[3] baud rate value */ TU_VERIFY(pl2303_encode_baud_rate(p_cdc, &buf[0])); @@ -2307,14 +2310,14 @@ static bool pl2303_set_line_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t compl /* For reference buf[4]=0 is 1 stop bits */ /* For reference buf[4]=1 is 1.5 stop bits */ /* For reference buf[4]=2 is 2 stop bits */ - buf[4] = p_cdc->requested_line_coding.stop_bits; // PL2303 has the same coding + buf[4] = p_cdc->requested_line.coding.stop_bits; // PL2303 has the same coding /* For reference buf[5]=0 is none parity */ /* For reference buf[5]=1 is odd parity */ /* For reference buf[5]=2 is even parity */ /* For reference buf[5]=3 is mark parity */ /* For reference buf[5]=4 is space parity */ - buf[5] = p_cdc->requested_line_coding.parity; // PL2303 has the same coding + buf[5] = p_cdc->requested_line.coding.parity; // PL2303 has the same coding return pl2303_set_request(p_cdc, PL2303_SET_LINE_REQUEST, PL2303_SET_LINE_REQUEST_TYPE, 0, 0, buf, PL2303_LINE_CODING_BUFSIZE, complete_cb, user_data); @@ -2350,45 +2353,45 @@ static void pl2303_internal_control_complete(tuh_xfer_t *xfer) { if (success) { if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && xfer->setup->bmRequestType == PL2303_SET_LINE_REQUEST_TYPE) { - p_cdc->line_coding = p_cdc->requested_line_coding; + p_cdc->line.coding = p_cdc->requested_line.coding; } if (xfer->setup->bRequest == PL2303_SET_CONTROL_REQUEST && xfer->setup->bmRequestType == PL2303_SET_CONTROL_REQUEST_TYPE) { - p_cdc->line_state = p_cdc->requested_line_state; + p_cdc->line.control_state = p_cdc->requested_line.control_state; } } - xfer->complete_cb = p_cdc->user_control_cb; + xfer->complete_cb = p_cdc->user_complete_cb; if (xfer->complete_cb) { xfer->complete_cb(xfer); } } static bool pl2303_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); return true; } static bool pl2303_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->requested_line_coding.bit_rate = p_cdc->line_coding.bit_rate; - p_cdc->user_control_cb = complete_cb; + p_cdc->requested_line.coding.bit_rate = p_cdc->line.coding.bit_rate; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); return true; } static bool pl2303_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->requested_line_coding.stop_bits = p_cdc->line_coding.stop_bits; - p_cdc->requested_line_coding.parity = p_cdc->line_coding.parity; - p_cdc->requested_line_coding.data_bits = p_cdc->line_coding.data_bits; - p_cdc->user_control_cb = complete_cb; + p_cdc->requested_line.coding.stop_bits = p_cdc->line.coding.stop_bits; + p_cdc->requested_line.coding.parity = p_cdc->line.coding.parity; + p_cdc->requested_line.coding.data_bits = p_cdc->line.coding.data_bits; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); return true; } static bool pl2303_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // PL2303 has the same bit coding - p_cdc->user_control_cb = complete_cb; + p_cdc->user_complete_cb = complete_cb; TU_ASSERT(pl2303_set_control_lines(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); return true; } @@ -2458,7 +2461,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { switch (state) { // from here sequence overtaken from Linux Kernel function pl2303_startup() case CONFIG_PL2303_DETECT_TYPE: - p_cdc->user_control_cb = cdch_process_set_config;// set once for whole process config + p_cdc->user_complete_cb = cdch_process_set_config;// set once for whole process config // get type and quirks (step 1) type = pl2303_detect_type(p_cdc, 1); TU_ASSERT(type != PL2303_TYPE_UNKNOWN); @@ -2606,7 +2609,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { // unnecessary pl2303_get_line_request() is skipped due to a stall case CONFIG_PL2303_LINE_CODING: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->requested_line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; TU_ASSERT(pl2303_set_line_request(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_MODEM_CONTROL)); break; #else @@ -2615,7 +2618,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { case CONFIG_PL2303_MODEM_CONTROL: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; + p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; TU_ASSERT(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_COMPLETE)); break; #else @@ -2861,7 +2864,7 @@ static uint32_t pl2303_encode_baud_rate_divisor_alt(uint8_t buf[PL2303_LINE_CODI } static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_LINE_CODING_BAUDRATE_BUFSIZE]) { - uint32_t baud = p_cdc->requested_line_coding.bit_rate; + uint32_t baud = p_cdc->requested_line.coding.bit_rate; uint32_t baud_sup; const pl2303_type_data_t* type_data = &pl2303_type_data[p_cdc->pl2303.type]; From 5c974cee23e9ece208df43b60070740fc2eda0c3 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Jun 2025 12:51:29 +0700 Subject: [PATCH 236/382] usbh make TU_API_SYNC() public, to implement sync() API, change return of sync API from uint8_t to tusb_xfer_result_t --- src/common/tusb_types.h | 2 ++ src/host/usbh.c | 47 ++------------------------ src/host/usbh.h | 73 ++++++++++++++++++++++++++--------------- 3 files changed, 51 insertions(+), 71 deletions(-) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ff5d8b66a..ec7aad796 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -278,6 +278,8 @@ typedef enum { XFER_RESULT_INVALID } xfer_result_t; +#define tusb_xfer_result_t xfer_result_t + // TODO remove enum { DESC_OFFSET_LEN = 0, diff --git a/src/host/usbh.c b/src/host/usbh.c index 08c362171..adaeef092 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1092,8 +1092,9 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) // generic helper to get a descriptor // if blocking, user_data is pointed to xfer_result -static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE static inline +bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { tusb_control_request_t const request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, @@ -1134,7 +1135,6 @@ bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer } //------------- String Descriptor -------------// - bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return _get_descriptor(daddr, TUSB_DESC_STRING, index, language_id, buffer, len, complete_cb, user_data); @@ -1272,47 +1272,6 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt, return tuh_control_xfer(&xfer); } -//--------------------------------------------------------------------+ -// Descriptor Sync -//--------------------------------------------------------------------+ - -#define _CONTROL_SYNC_API(_async_func, ...) \ - xfer_result_t result = XFER_RESULT_INVALID;\ - TU_VERIFY(_async_func(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \ - return (uint8_t) result - -uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get, daddr, type, index, buffer, len); -} - -uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_device, daddr, buffer, len); -} - -uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_configuration, daddr, index, buffer, len); -} - -uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_hid_report, daddr, itf_num, desc_type, index, buffer, len); -} - -uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_string, daddr, index, language_id, buffer, len); -} - -uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, daddr, language_id, buffer, len); -} - -uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_product_string, daddr, language_id, buffer, len); -} - -uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { - _CONTROL_SYNC_API(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len); -} - //--------------------------------------------------------------------+ // Detaching //--------------------------------------------------------------------+ diff --git a/src/host/usbh.h b/src/host/usbh.h index 1ee511722..1e9bb26bc 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -234,8 +234,18 @@ bool tuh_bus_info_get(uint8_t daddr, tuh_bus_info_t* bus_info); //--------------------------------------------------------------------+ // Transfer API +// Each Function will make a USB transfer request to device. If +// - complete_cb != NULL, the function will return immediately and invoke the callback when request is complete. +// - complete_cb == NULL, the function will block until request is complete. +// In this case, user_data should be tusb_xfer_result_t* to hold the transfer result. //--------------------------------------------------------------------+ +// Helper to make Sync API from async one +#define TU_API_SYNC(_async_api, ...) \ + xfer_result_t result = XFER_RESULT_INVALID;\ + TU_VERIFY(_async_api(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \ + return result + // Submit a control transfer // - async: complete callback invoked when finished. // - sync : blocking if complete callback is NULL. @@ -327,45 +337,54 @@ bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* //--------------------------------------------------------------------+ // Descriptors Synchronous (blocking) +// Sync API which is blocking until transfer is complete. +// return transfer result //--------------------------------------------------------------------+ -// Sync (blocking) version of tuh_descriptor_get() -// return transfer result -uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len); +// Sync version of tuh_descriptor_get() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get, daddr, type, index, buffer, len); +} -// Sync (blocking) version of tuh_descriptor_get_device() -// return transfer result -uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len); +// Sync version of tuh_descriptor_get_device() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_device, daddr, buffer, len); +} -// Sync (blocking) version of tuh_descriptor_get_configuration() -// return transfer result -uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len); +// Sync version of tuh_descriptor_get_configuration() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_configuration, daddr, index, buffer, len); +} -// Sync (blocking) version of tuh_descriptor_get_hid_report() -// return transfer result -uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len); +// Sync version of tuh_descriptor_get_hid_report() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_hid_report, daddr, itf_num, desc_type, index, buffer, len); +} -// Sync (blocking) version of tuh_descriptor_get_string() -// return transfer result -uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len); +// Sync version of tuh_descriptor_get_string() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_string, daddr, index, language_id, buffer, len); +} -// Sync (blocking) version of tuh_descriptor_get_string_langid() -TU_ATTR_ALWAYS_INLINE static inline -uint8_t tuh_descriptor_get_string_langid_sync(uint8_t daddr, void* buffer, uint16_t len) { +// Sync version of tuh_descriptor_get_string_langid() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_string_langid_sync(uint8_t daddr, void* buffer, uint16_t len) { return tuh_descriptor_get_string_sync(daddr, 0, 0, buffer, len); } -// Sync (blocking) version of tuh_descriptor_get_manufacturer_string() -// return transfer result -uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len); +// Sync version of tuh_descriptor_get_manufacturer_string() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_manufacturer_string, daddr, language_id, buffer, len); +} -// Sync (blocking) version of tuh_descriptor_get_product_string() -// return transfer result -uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len); +// Sync version of tuh_descriptor_get_product_string() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_product_string, daddr, language_id, buffer, len); +} -// Sync (blocking) version of tuh_descriptor_get_serial_string() -// return transfer result -uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len); +// Sync version of tuh_descriptor_get_serial_string() +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) { + TU_API_SYNC(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len); +} #ifdef __cplusplus } From adf6cbfe03523cd8f7e23cb7f2edbb4304a6cd89 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Jun 2025 12:52:34 +0700 Subject: [PATCH 237/382] cdch clean up and refactor, add explicit sync() API --- examples/host/cdc_msc_hid/src/cdc_app.c | 2 +- src/class/cdc/cdc_host.c | 172 ++++++++++-------------- src/class/cdc/cdc_host.h | 48 ++++++- src/class/cdc/serial/pl2303.h | 33 ++--- 4 files changed, 127 insertions(+), 128 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index 6f4433f22..2fa9a8560 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -89,7 +89,7 @@ void tuh_cdc_mount_cb(uint8_t idx) { // If CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined, line coding will be set by tinyusb stack // while eneumerating new cdc device cdc_line_coding_t line_coding = {0}; - if (tuh_cdc_get_local_line_coding(idx, &line_coding)) { + if (tuh_cdc_get_line_coding_local(idx, &line_coding)) { printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits); printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits); } diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 2fe2c85bc..50d0a020d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -42,15 +42,15 @@ // Level where CFG_TUSB_DEBUG must be at least for this driver is logged #ifndef CFG_TUH_CDC_LOG_LEVEL - #define CFG_TUH_CDC_LOG_LEVEL CFG_TUH_LOG_LEVEL + #define CFG_TUH_CDC_LOG_LEVEL 1 #endif -#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) -#define TU_LOG_CDC(TXT,DADDR,ITF_NUM,NAME,...) TU_LOG_DRV("[:%u:%u] CDCh %s " TXT "\r\n", \ - DADDR, ITF_NUM, NAME, ##__VA_ARGS__) -#define TU_LOG_P_CDC(TXT,...) TU_LOG_CDC(TXT, p_cdc->daddr, p_cdc->bInterfaceNumber, \ - serial_drivers[p_cdc->serial_drid].name, ##__VA_ARGS__) -#define TU_LOG_P_CDC_BOOL(TXT,VAL) TU_LOG_P_CDC(TXT " " #VAL " = %d", VAL) +#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) +#define TU_LOG_CDC(_cdc, _format, ...) TU_LOG_DRV("[:%u:%u] CDCh %s " _format "\r\n", _cdc->daddr, _cdc->bInterfaceNumber, \ + serial_drivers[_cdc->serial_drid].name, ##__VA_ARGS__) + +// Driver that need to set line coding in two stages: baudrate then data format. +#define DRIVER_2STAGE_SET_LINE_CODING (CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X) //--------------------------------------------------------------------+ // Host CDC Interface @@ -72,7 +72,8 @@ typedef struct { } line, requested_line; tuh_xfer_cb_t user_complete_cb; // required since we handle request internally first - #if CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X + + #if DRIVER_2STAGE_SET_LINE_CODING tuh_xfer_cb_t requested_complete_cb; #endif @@ -197,49 +198,57 @@ enum { SERIAL_DRIVER_COUNT }; +typedef bool (*serial_driver_func_t)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + typedef struct { uint16_t const (*vid_pid_list)[2]; uint16_t const vid_pid_count; + bool is_2stage_line_coding; // true if driver requires to set baudrate then data format separately + bool (*const open)(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); bool (*const process_set_config)(tuh_xfer_t * xfer); - bool (*const set_control_line_state)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_baudrate)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_data_format)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); - bool (*const set_line_coding)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + const serial_driver_func_t set_control_line_state; + const serial_driver_func_t set_baudrate; + const serial_driver_func_t set_data_format; + const serial_driver_func_t set_line_coding; #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - uint8_t const * name; + const char * name; #endif } cdch_serial_driver_t; +#if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL + #define DRIVER_NAME_DECLARE(_str) .name = _str +#else + #define DRIVER_NAME_DECLARE(_str) +#endif + // Note driver list must be in the same order as SERIAL_DRIVER enum static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = NULL, .vid_pid_count = 0, + .is_2stage_line_coding = false, .open = acm_open, .process_set_config = acm_process_set_config, .set_control_line_state = acm_set_control_line_state, .set_baudrate = acm_set_baudrate, .set_data_format = acm_set_data_format, .set_line_coding = acm_set_line_coding, - #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - .name = (uint8_t const *) "ACM" - #endif + DRIVER_NAME_DECLARE("ACM") }, #if CFG_TUH_CDC_FTDI { .vid_pid_list = ftdi_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(ftdi_vid_pid_list), + .is_2stage_line_coding = true, .open = ftdi_open, .process_set_config = ftdi_proccess_set_config, .set_control_line_state = ftdi_set_modem_ctrl, .set_baudrate = ftdi_set_baudrate, .set_data_format = ftdi_set_data_format, .set_line_coding = ftdi_set_line_coding, - #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - .name = (uint8_t const *) "FTDI" - #endif + DRIVER_NAME_DECLARE("FTDI") }, #endif @@ -247,15 +256,14 @@ static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = cp210x_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(cp210x_vid_pid_list), + .is_2stage_line_coding = true, .open = cp210x_open, .process_set_config = cp210x_process_set_config, .set_control_line_state = cp210x_set_modem_ctrl, .set_baudrate = cp210x_set_baudrate, .set_data_format = cp210x_set_data_format, .set_line_coding = cp210x_set_line_coding, - #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - .name = (uint8_t const *) "CP210x" - #endif + DRIVER_NAME_DECLARE("CP210x") }, #endif @@ -263,15 +271,14 @@ static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = ch34x_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(ch34x_vid_pid_list), + .is_2stage_line_coding = true, .open = ch34x_open, .process_set_config = ch34x_process_set_config, .set_control_line_state = ch34x_set_modem_ctrl, .set_baudrate = ch34x_set_baudrate, .set_data_format = ch34x_set_data_format, .set_line_coding = ch34x_set_line_coding, - #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - .name = (uint8_t const *) "CH34x" - #endif + DRIVER_NAME_DECLARE("CH34x") }, #endif @@ -279,15 +286,14 @@ static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = pl2303_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(pl2303_vid_pid_list), + .is_2stage_line_coding = false, .open = pl2303_open, .process_set_config = pl2303_process_set_config, .set_control_line_state = pl2303_set_modem_ctrl, .set_baudrate = pl2303_set_baudrate, .set_data_format = pl2303_set_data_format, .set_line_coding = pl2303_set_line_coding, - #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL - .name = (uint8_t const *) "PL2303" - #endif + DRIVER_NAME_DECLARE("PL2303") } #endif }; @@ -440,13 +446,7 @@ bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t* line_state) { bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t * line_coding) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - *line_coding = p_cdc->line.coding; - TU_LOG_P_CDC("get line coding %lu %u%c%s", - p_cdc->line.coding.bit_rate, p_cdc->line.coding.data_bits, - CDC_LINE_CODING_PARITY_CHAR(p_cdc->line.coding.parity), - CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); - return true; } @@ -520,29 +520,27 @@ bool tuh_cdc_read_clear (uint8_t idx) { // Control Endpoint API //--------------------------------------------------------------------+ +#if DRIVER_2STAGE_SET_LINE_CODING + // set line coding using sequence with 2 stages: set baudrate (stage1) + set data format (stage2) static bool set_line_coding_sequence( cdch_interface_t * p_cdc, - // control request function to set baudrate - bool (*set_baudrate_request)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data), - // control request function to set data format - bool (*set_data_format_request)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data), - // function to be called after stage 1 completed - void (*set_line_coding_stage1_complete)(tuh_xfer_t * xfer), - // control complete function to be called after request - void (*internal_control_complete)(tuh_xfer_t * xfer), + serial_driver_func_t set_baudrate, + serial_driver_func_t set_data_format, + tuh_xfer_cb_t set_line_coding_stage1_complete, // function to be called after stage 1 completed + tuh_xfer_cb_t internal_control_complete, // control complete function to be called after request tuh_xfer_cb_t complete_cb, uintptr_t user_data) { if (complete_cb) { // non-blocking // stage 1 set baudrate p_cdc->requested_complete_cb = complete_cb; // store complete_cb to be used in set_line_coding_stage1_complete() p_cdc->user_complete_cb = set_line_coding_stage1_complete; - return set_baudrate_request(p_cdc, internal_control_complete, user_data); + return set_baudrate(p_cdc, internal_control_complete, user_data); } else { // blocking sequence // stage 1 set baudrate xfer_result_t result = XFER_RESULT_INVALID; // use local result, because user_data ptr may be NULL - bool ret = set_baudrate_request(p_cdc, NULL, (uintptr_t) &result); + bool ret = set_baudrate(p_cdc, NULL, (uintptr_t) &result); if (user_data) { *((xfer_result_t *) user_data) = result; @@ -556,7 +554,7 @@ static bool set_line_coding_sequence( // stage 2 set data format result = XFER_RESULT_INVALID; - ret = set_data_format_request(p_cdc, NULL, (uintptr_t) &result); + ret = set_data_format(p_cdc, NULL, (uintptr_t) &result); if (user_data) { *((xfer_result_t *) user_data) = result; @@ -590,58 +588,35 @@ static void set_line_coding_stage1_complete( } } } - -// call of (non-)blocking set-functions (to set line state, baudrate, ...) -static bool set_function_call ( - cdch_interface_t * p_cdc, - bool (*set_function)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data), - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - if (complete_cb) { - // non-blocking with call back - return set_function(p_cdc, complete_cb, user_data); - } else { - // blocking - xfer_result_t result = XFER_RESULT_INVALID; // use local result, because user_data ptr may be NULL - bool ret = set_function(p_cdc, NULL, (uintptr_t) &result); - - if (user_data) { - *((xfer_result_t *) user_data) = result; - } - - return (ret && result == XFER_RESULT_SUCCESS); - } -} +#endif bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); + TU_LOG_CDC(p_cdc, "set control line state dtr = %u rts = %u", p_cdc->requested_line.control_state.dtr, p_cdc->requested_line.control_state.rts); cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line.control_state.value = (uint8_t) line_state; - TU_LOG_P_CDC("set control line state dtr = %u rts = %u", p_cdc->requested_line.control_state.dtr, p_cdc->requested_line.control_state.rts); - - const bool ret = set_function_call(p_cdc, driver->set_control_line_state, complete_cb, user_data); - + const bool ret = driver->set_control_line_state(p_cdc, complete_cb, user_data); if (ret && !complete_cb) { - p_cdc->line.control_state = p_cdc->requested_line.control_state; + // blocking, update line state if request was successful + p_cdc->line.control_state.value = (uint8_t) line_state; } + return ret; } bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set baudrate %lu", baudrate); + TU_LOG_CDC(p_cdc, "set baudrate %lu", baudrate); cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line.coding.bit_rate = baudrate; - - bool ret = set_function_call(p_cdc, driver->set_baudrate, complete_cb, user_data); - + const bool ret = driver->set_baudrate(p_cdc, complete_cb, user_data); if (ret && !complete_cb) { p_cdc->line.coding.bit_rate = baudrate; } -// TU_LOG_P_CDC_BOOL("set baudrate", ret); return ret; } @@ -650,7 +625,7 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set data format %u%c%s", + TU_LOG_CDC(p_cdc, "set data format %u%c%s", data_bits, CDC_LINE_CODING_PARITY_CHAR(parity), CDC_LINE_CODING_STOP_BITS_TEXT(stop_bits)); cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; @@ -659,15 +634,13 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin p_cdc->requested_line.coding.parity = parity; p_cdc->requested_line.coding.data_bits = data_bits; - bool ret = set_function_call(p_cdc, driver->set_data_format, complete_cb, user_data); + const bool ret = driver->set_data_format(p_cdc, complete_cb, user_data); if (ret && !complete_cb) { p_cdc->line.coding.stop_bits = stop_bits; p_cdc->line.coding.parity = parity; p_cdc->line.coding.data_bits = data_bits; } -// TU_LOG_P_CDC_BOOL("set data format", ret); - return ret; } @@ -675,7 +648,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set line coding %lu %u%c%s", + TU_LOG_CDC(p_cdc, "set line coding %lu %u%c%s", line_coding->bit_rate, line_coding->data_bits, CDC_LINE_CODING_PARITY_CHAR(line_coding->parity), CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); @@ -683,12 +656,11 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, p_cdc->requested_line.coding = *line_coding; - bool ret = set_function_call(p_cdc, driver->set_line_coding, complete_cb, user_data); + const bool ret = driver->set_line_coding(p_cdc, complete_cb, user_data); if (ret && !complete_cb) { p_cdc->line.coding = *line_coding; } -// TU_LOG_P_CDC_BOOL("set line coding", ret); return ret; } @@ -728,7 +700,7 @@ void cdch_close(uint8_t daddr) { for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { cdch_interface_t *p_cdc = &cdch_data[idx]; if (p_cdc->daddr == daddr) { - TU_LOG_P_CDC("close"); + TU_LOG_CDC(p_cdc, "close"); // Invoke application callback if (tuh_cdc_umount_cb) { @@ -847,9 +819,8 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d } if (driver_detected) { - TU_LOG_CDC("open", daddr, itf_desc->bInterfaceNumber, driver_detected->name); - bool ret = driver_detected->open(daddr, itf_desc, max_len); - // TU_LOG_CDC("opened ret = %s", daddr, itf_desc->bInterfaceNumber, driver_detected->name, ret ? "true" : "FALSE" ); + const bool ret = driver_detected->open(daddr, itf_desc, max_len); + TU_LOG_DRV("[:%u:%u] CDCh %s open %s\r\n", daddr, itf_desc->bInterfaceNumber, driver_detected->name, ret ? "OK" : "FAILED"); return ret; } @@ -859,7 +830,6 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d static void set_config_complete(uint8_t idx, uint8_t itf_offset, bool success) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); - TU_LOG_P_CDC_BOOL("set config complete", success); if (success) { p_cdc->mounted = true; @@ -883,6 +853,8 @@ static void cdch_process_set_config(tuh_xfer_t *xfer) { TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); const uint8_t idx = get_idx_by_ptr(p_cdc); + TU_LOG_DRV(" state = %u\r\n", xfer->user_data); + if (!serial_drivers[p_cdc->serial_drid].process_set_config(xfer)) { const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; set_config_complete(idx, itf_offset, false); @@ -895,7 +867,7 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { uint8_t const idx = tuh_cdc_itf_get_index(daddr, itf_num); cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); - TU_LOG_P_CDC("set config"); + TU_LOG_CDC(p_cdc, "set config"); // fake transfer to kick-off process_set_config() tuh_xfer_t xfer; @@ -919,7 +891,6 @@ static void acm_internal_control_complete(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC_BOOL("control complete", success); if (success) { switch (xfer->setup->bRequest) { @@ -1204,7 +1175,6 @@ static void ftdi_internal_control_complete(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC_BOOL("control complete", success); if (success) { if (xfer->setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST && @@ -1232,14 +1202,12 @@ static void ftdi_internal_control_complete(tuh_xfer_t *xfer) { static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; TU_ASSERT(ftdi_set_data_request(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); - return true; } static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; TU_ASSERT(ftdi_change_speed(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); - return true; } @@ -1271,7 +1239,6 @@ static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ } //------------- Enumeration -------------// - enum { CONFIG_FTDI_DETERMINE_TYPE = 0, CONFIG_FTDI_WRITE_LATENCY, @@ -1448,7 +1415,7 @@ static bool ftdi_determine_type(cdch_interface_t *p_cdc) { #if CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL const char * ftdi_chip_name[] = { FTDI_CHIP_NAMES }; - TU_LOG_P_CDC("%s detected (bcdDevice = 0x%04x)", + TU_LOG_CDC(p_cdc, "%s detected (bcdDevice = 0x%04x)", ftdi_chip_name[p_cdc->ftdi.chip_type], version); #endif @@ -1595,7 +1562,7 @@ static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { break; } - TU_LOG_P_CDC("Baudrate divisor = 0x%lu", div_value); + TU_LOG_CDC(p_cdc, "Baudrate divisor = 0x%lu", div_value); return div_value; } @@ -1695,7 +1662,6 @@ static void cp210x_internal_control_complete(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC_BOOL("control complete", success); if (success) { switch (xfer->setup->bRequest) { @@ -1795,7 +1761,7 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); - switch (state) { + switch (state) { case CONFIG_CP210X_IFC_ENABLE: TU_ASSERT(cp210x_ifc_enable(p_cdc, CP210X_UART_ENABLE, cdch_process_set_config, CONFIG_CP210X_SET_BAUDRATE_REQUEST)); break; @@ -1941,7 +1907,6 @@ static void ch34x_internal_control_complete(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC_BOOL("control complete", success); if (success) { switch (xfer->setup->bRequest) { @@ -2059,7 +2024,6 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); cdch_interface_t *p_cdc = get_itf(idx); uint8_t buffer[2];// TODO remove - TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); switch (state) { @@ -2071,7 +2035,7 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { case CONFIG_CH34X_SERIAL_INIT: { // handle version read data, set CH34x line coding (incl. baudrate) uint8_t const version = xfer->buffer[0]; - TU_LOG_P_CDC("Chip Version = 0x%02x", version); + TU_LOG_CDC(p_cdc, "Chip Version = 0x%02x", version); // only versions >= 0x30 are tested, below 0x30 seems having other programming // see drivers from WCH vendor, Linux kernel and FreeBSD if (version >= 0x30) { @@ -2348,7 +2312,6 @@ static void pl2303_internal_control_complete(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf(idx); TU_ASSERT(p_cdc, ); bool const success = (xfer->result == XFER_RESULT_SUCCESS); - TU_LOG_P_CDC_BOOL("control complete", success); if (success) { if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && @@ -2458,6 +2421,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { pl2303_type_t type; TU_ASSERT(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || state == CONFIG_PL2303_READ1)); + switch (state) { // from here sequence overtaken from Linux Kernel function pl2303_startup() case CONFIG_PL2303_DETECT_TYPE: @@ -2741,7 +2705,7 @@ static pl2303_type_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step) { default: break; } - TU_LOG_P_CDC("unknown device type bcdUSB = 0x%04x", desc_dev.bcdUSB); + TU_LOG_CDC(p_cdc, "unknown device type bcdUSB = 0x%04x", desc_dev.bcdUSB); return PL2303_TYPE_UNKNOWN; } @@ -2886,7 +2850,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_ } else { baud = pl2303_encode_baud_rate_divisor(buf, baud); } - TU_LOG_P_CDC("real baudrate %lu", baud); + TU_LOG_CDC(p_cdc, "real baudrate %lu", baud); return true; } diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index 688164cb2..37bfca270 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -137,13 +137,12 @@ bool tuh_cdc_peek(uint8_t idx, uint8_t* ch); bool tuh_cdc_read_clear (uint8_t idx); //--------------------------------------------------------------------+ -// Control Endpoint (Request) API +// Control Request API // Each Function will make a USB control transfer request to/from device // - If complete_cb is provided, the function will return immediately and invoke // the callback when request is complete. // - If complete_cb is NULL, the function will block until request is complete. -// - In this case, user_data should be pointed to xfer_result_t to hold the transfer result. -// - The function will return true if transfer is successful, false otherwise. +// In this case, user_data should be usb_xfer_result_t* to hold the transfer result. //--------------------------------------------------------------------+ // Request to Set Control Line State: DTR (bit 0), RTS (bit 1) @@ -179,17 +178,52 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, // bool tuh_cdc_get_line_coding(uint8_t idx, cdc_line_coding_t* coding); // Connect by set both DTR, RTS -TU_ATTR_ALWAYS_INLINE static inline -bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return tuh_cdc_set_control_line_state(idx, CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS, complete_cb, user_data); } // Disconnect by clear both DTR, RTS -TU_ATTR_ALWAYS_INLINE static inline -bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return tuh_cdc_set_control_line_state(idx, 0x00, complete_cb, user_data); } +//--------------------------------------------------------------------+ +// Control Request Sync API +// Each Function will make a USB control transfer request to/from device the function will block until request is +// complete. The function will return the transfer request result +//--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_control_line_state_sync(uint8_t idx, uint16_t line_state) { + TU_API_SYNC(tuh_cdc_set_control_line_state, idx, line_state); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_dtr_sync(uint8_t idx, bool dtr_state) { + TU_API_SYNC(tuh_cdc_set_dtr, idx, dtr_state); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_rts_sync(uint8_t idx, bool rts_state) { + TU_API_SYNC(tuh_cdc_set_rts, idx, rts_state); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_baudrate_sync(uint8_t idx, uint32_t baudrate) { + TU_API_SYNC(tuh_cdc_set_baudrate, idx, baudrate); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_data_format_sync(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits) { + TU_API_SYNC(tuh_cdc_set_data_format, idx, stop_bits, parity, data_bits); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_line_coding_sync(uint8_t idx, cdc_line_coding_t const* line_coding) { + TU_API_SYNC(tuh_cdc_set_line_coding, idx, line_coding); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_connect_sync(uint8_t idx) { + TU_API_SYNC(tuh_cdc_connect, idx); +} + +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_disconnect_sync(uint8_t idx) { + TU_API_SYNC(tuh_cdc_disconnect, idx); +} + //--------------------------------------------------------------------+ // CDC APPLICATION CALLBACKS //--------------------------------------------------------------------+ diff --git a/src/class/cdc/serial/pl2303.h b/src/class/cdc/serial/pl2303.h index c01dac0e1..63910c7bb 100644 --- a/src/class/cdc/serial/pl2303.h +++ b/src/class/cdc/serial/pl2303.h @@ -109,36 +109,37 @@ typedef enum pl2303_type { } pl2303_type_t; typedef struct pl2303_type_data { - uint32_t const max_baud_rate; - uint8_t const quirks; - uint8_t const no_autoxonxoff : 1; - uint8_t const no_divisors : 1; - uint8_t const alt_divisors : 1; + uint32_t max_baud_rate; + uint8_t quirks; + uint8_t no_autoxonxoff : 1; + uint8_t no_divisors : 1; + uint8_t alt_divisors : 1; } pl2303_type_data_t; #define PL2303_TYPE_DATA \ [PL2303_TYPE_H] = { \ - .max_baud_rate = 1228800, \ - .quirks = PL2303_QUIRK_LEGACY, \ - .no_autoxonxoff = true, \ + .max_baud_rate = 1228800, .quirks = PL2303_QUIRK_LEGACY, \ + .no_autoxonxoff = 1, .no_divisors = 0, .alt_divisors = 0 \ }, \ [PL2303_TYPE_HX] = { \ - .max_baud_rate = 6000000, \ + .max_baud_rate = 6000000, .quirks = 0, \ + .no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 0 \ }, \ [PL2303_TYPE_TA] = { \ - .max_baud_rate = 6000000, \ - .alt_divisors = true, \ + .max_baud_rate = 6000000, .quirks = 0, \ + .no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 1 \ }, \ [PL2303_TYPE_TB] = { \ - .max_baud_rate = 12000000, \ - .alt_divisors = true, \ + .max_baud_rate = 12000000, .quirks = 0, \ + .no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 1 \ }, \ [PL2303_TYPE_HXD] = { \ - .max_baud_rate = 12000000, \ + .max_baud_rate = 12000000, .quirks = 0, \ + .no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 0 \ }, \ [PL2303_TYPE_HXN] = { \ - .max_baud_rate = 12000000, \ - .no_divisors = true, \ + .max_baud_rate = 12000000, .quirks = 0, \ + .no_autoxonxoff = 0, .no_divisors = 1, .alt_divisors = 0 \ } typedef struct TU_ATTR_PACKED { From 900d0d974b177959ffeaa1f34de72daf2ef72694 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Jun 2025 17:04:40 +0700 Subject: [PATCH 238/382] refactor change signature of serial driver's process_set_config adding serial driver's request_complete() --- src/class/cdc/cdc_host.c | 185 ++++++++++++++++++--------------------- 1 file changed, 84 insertions(+), 101 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 50d0a020d..f36487758 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -112,11 +112,13 @@ CFG_TUH_MEM_SECTION static cdch_epbuf_t cdch_epbuf[CFG_TUH_CDC]; // Serial Driver //--------------------------------------------------------------------+ +// General driver static void cdch_process_set_config(tuh_xfer_t *xfer); +static void cdch_internal_control_complete(tuh_xfer_t *xfer); //------------- ACM prototypes -------------// static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool acm_process_set_config(tuh_xfer_t * xfer); +static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); static bool acm_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -127,7 +129,8 @@ static bool acm_set_control_line_state(cdch_interface_t * p_cdc, tuh_xfer_cb_t c #if CFG_TUH_CDC_FTDI static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST}; static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); -static bool ftdi_proccess_set_config(tuh_xfer_t * xfer); +static bool ftdi_proccess_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void ftdi_internal_control_complete(cdch_interface_t* p_cdc, tuh_xfer_t *xfer); static bool ftdi_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ftdi_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -140,7 +143,9 @@ static bool ftdi_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIST}; static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool cp210x_process_set_config(tuh_xfer_t * xfer); +static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void acm_internal_control_complete(tuh_xfer_t *xfer); +static void cp210x_internal_control_complete(tuh_xfer_t *xfer); static bool cp210x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool cp210x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -153,7 +158,8 @@ static bool cp210x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t comple static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST}; static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool ch34x_process_set_config(tuh_xfer_t *xfer); +static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void ch34x_internal_control_complete(tuh_xfer_t *xfer); static bool ch34x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ch34x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -167,7 +173,8 @@ static uint16_t const pl2303_vid_pid_list[][2] = {CFG_TUH_CDC_PL2303_VID_PID_LIS static const pl2303_type_data_t pl2303_type_data[PL2303_TYPE_COUNT] = {PL2303_TYPE_DATA}; static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool pl2303_process_set_config(tuh_xfer_t *xfer); +static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void pl2303_internal_control_complete(tuh_xfer_t *xfer); static bool pl2303_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool pl2303_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -206,11 +213,11 @@ typedef struct { bool is_2stage_line_coding; // true if driver requires to set baudrate then data format separately bool (*const open)(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); - bool (*const process_set_config)(tuh_xfer_t * xfer); - const serial_driver_func_t set_control_line_state; - const serial_driver_func_t set_baudrate; - const serial_driver_func_t set_data_format; - const serial_driver_func_t set_line_coding; + bool (*const process_set_config)(cdch_interface_t * p_cdc, tuh_xfer_t * xfer); + void (*const request_complete)(cdch_interface_t * p_cdc, tuh_xfer_t * xfer); // internal request complete handler to update line state + + serial_driver_func_t set_control_line_state, set_baudrate, set_data_format, set_line_coding; + #if CFG_TUSB_DEBUG && CFG_TUSB_DEBUG >= CFG_TUH_CDC_LOG_LEVEL const char * name; #endif @@ -244,6 +251,7 @@ static const cdch_serial_driver_t serial_drivers[] = { .is_2stage_line_coding = true, .open = ftdi_open, .process_set_config = ftdi_proccess_set_config, + .request_complete = ftdi_internal_control_complete, .set_control_line_state = ftdi_set_modem_ctrl, .set_baudrate = ftdi_set_baudrate, .set_data_format = ftdi_set_data_format, @@ -827,11 +835,9 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d return false; } -static void set_config_complete(uint8_t idx, uint8_t itf_offset, bool success) { - cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - +static void set_config_complete(cdch_interface_t *p_cdc, uint8_t itf_offset, bool success) { if (success) { + const uint8_t idx = get_idx_by_ptr(p_cdc); p_cdc->mounted = true; if (tuh_cdc_mount_cb) { tuh_cdc_mount_cb(idx); @@ -848,19 +854,6 @@ static void set_config_complete(uint8_t idx, uint8_t itf_offset, bool success) { usbh_driver_set_config_complete(p_cdc->daddr, p_cdc->bInterfaceNumber + itf_offset); } -static void cdch_process_set_config(tuh_xfer_t *xfer) { - cdch_interface_t *p_cdc = get_itf_by_xfer(xfer); - TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); - const uint8_t idx = get_idx_by_ptr(p_cdc); - - TU_LOG_DRV(" state = %u\r\n", xfer->user_data); - - if (!serial_drivers[p_cdc->serial_drid].process_set_config(xfer)) { - const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; - set_config_complete(idx, itf_offset, false); - } -} - bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { tusb_control_request_t request; request.wIndex = tu_htole16((uint16_t) itf_num); @@ -880,6 +873,32 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { return true; } + +static void cdch_process_set_config(tuh_xfer_t *xfer) { + cdch_interface_t *p_cdc = get_itf_by_xfer(xfer); + TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); + TU_LOG_DRV(" state = %u\r\n", xfer->user_data); + + if (!serial_drivers[p_cdc->serial_drid].process_set_config(p_cdc, xfer)) { + const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; + set_config_complete(p_cdc, itf_offset, false); + } +} + +static void cdch_internal_control_complete(tuh_xfer_t *xfer) { + cdch_interface_t *p_cdc = get_itf_by_xfer(xfer); + TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); + + TU_LOG_DRV(" request result = %u\r\n", xfer->result); + serial_drivers[p_cdc->serial_drid].request_complete(p_cdc, xfer); + + // Invoke application callback + xfer->complete_cb = p_cdc->user_complete_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } +} + //--------------------------------------------------------------------+ // ACM //--------------------------------------------------------------------+ @@ -1046,13 +1065,9 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint1 return true; } -static bool acm_process_set_config(tuh_xfer_t *xfer) { +static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); const uintptr_t state = xfer->user_data; - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); - switch (state) { case CONFIG_ACM_SET_CONTROL_LINE_STATE: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM @@ -1076,7 +1091,7 @@ static bool acm_process_set_config(tuh_xfer_t *xfer) { case CONFIG_ACM_COMPLETE: // itf_num+1 to account for data interface as well - set_config_complete(idx, 1, true); + set_config_complete(p_cdc, 1, true); break; default: @@ -1159,55 +1174,38 @@ static bool ftdi_set_data_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet value, p_cdc->ftdi.channel, complete_cb, user_data); } -static inline bool ftdi_update_mctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint16_t value = (uint16_t) ((p_cdc->requested_line.control_state.dtr ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW) | - (p_cdc->requested_line.control_state.rts ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW)); - - return ftdi_set_request(p_cdc, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - value, p_cdc->ftdi.channel, complete_cb, user_data); -} - //------------- Driver API -------------// // internal control complete to update state such as line state, line_coding -static void ftdi_internal_control_complete(tuh_xfer_t *xfer) { - uint8_t const idx = ftdi_get_idx(xfer); - cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - bool const success = (xfer->result == XFER_RESULT_SUCCESS); - - if (success) { - if (xfer->setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST && - xfer->setup->bmRequestType == FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE ) { +static void ftdi_internal_control_complete(cdch_interface_t* p_cdc, tuh_xfer_t *xfer) { + const tusb_control_request_t * setup = xfer->setup; + if (xfer->result == XFER_RESULT_SUCCESS) { + if (setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST && + setup->bmRequestType == FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE ) { p_cdc->line.control_state = p_cdc->requested_line.control_state; } - if (xfer->setup->bRequest == FTDI_SIO_SET_DATA_REQUEST && - xfer->setup->bmRequestType == FTDI_SIO_SET_DATA_REQUEST_TYPE ) { + if (setup->bRequest == FTDI_SIO_SET_DATA_REQUEST && + setup->bmRequestType == FTDI_SIO_SET_DATA_REQUEST_TYPE ) { p_cdc->line.coding.stop_bits = p_cdc->requested_line.coding.stop_bits; p_cdc->line.coding.parity = p_cdc->requested_line.coding.parity; p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits; } - if (xfer->setup->bRequest == FTDI_SIO_SET_BAUDRATE_REQUEST && - xfer->setup->bmRequestType == FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE ) { + if (setup->bRequest == FTDI_SIO_SET_BAUDRATE_REQUEST && + setup->bmRequestType == FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE ) { p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; } } - - xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { - xfer->complete_cb(xfer); - } } static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(ftdi_set_data_request(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); + TU_ASSERT(ftdi_set_data_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(ftdi_change_speed(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); + TU_ASSERT(ftdi_change_speed(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } @@ -1218,7 +1216,7 @@ static void ftdi_set_line_coding_stage1_complete(tuh_xfer_t *xfer) { uint8_t const itf_num = p_cdc->bInterfaceNumber; set_line_coding_stage1_complete(xfer, itf_num, ftdi_set_data_request, // control request function to set data format - ftdi_internal_control_complete); // control complete function to be called after request + cdch_internal_control_complete); // control complete function to be called after request } // 2 stages: set baudrate (stage1) + set data format (stage2) @@ -1227,15 +1225,16 @@ static bool ftdi_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complet ftdi_change_speed, // control request function to set baudrate ftdi_set_data_request, // control request function to set data format ftdi_set_line_coding_stage1_complete, // function to be called after stage 1 completed - ftdi_internal_control_complete, // control complete function to be called after request + cdch_internal_control_complete, // control complete function to be called after request complete_cb, user_data); } static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + uint16_t line_state = (uint16_t) ((p_cdc->requested_line.control_state.dtr ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW) | + (p_cdc->requested_line.control_state.rts ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW)); p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(ftdi_update_mctrl(p_cdc, complete_cb ? ftdi_internal_control_complete : NULL, user_data)); - - return true; + return ftdi_set_request(p_cdc, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + line_state, p_cdc->ftdi.channel, complete_cb ? cdch_internal_control_complete : NULL, user_data); } //------------- Enumeration -------------// @@ -1274,18 +1273,14 @@ static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint return open_ep_stream_pair(p_cdc, desc_ep); } -static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { +static bool ftdi_proccess_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); const uintptr_t state = xfer->user_data; - uint8_t const idx = ftdi_get_idx(xfer); - cdch_interface_t *p_cdc = get_itf(idx); - uint8_t const itf_num = p_cdc->bInterfaceNumber; - TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); - switch (state) { // from here sequence overtaken from Linux Kernel function ftdi_port_probe() case CONFIG_FTDI_DETERMINE_TYPE: // determine type - if (itf_num == 0) { + if (p_cdc->bInterfaceNumber == 0) { TU_ASSERT(ftdi_determine_type(p_cdc)); } else { // other interfaces have same type as interface 0 @@ -1318,7 +1313,7 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(ftdi_set_data_request(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_SET_BAUDRATE)); + TU_ASSERT(ftdi_set_data_request(p_cdc, cdch_internal_control_complete, CONFIG_FTDI_SET_BAUDRATE)); break; #else TU_ATTR_FALLTHROUGH; @@ -1327,7 +1322,7 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { case CONFIG_FTDI_SET_BAUDRATE: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(ftdi_change_speed(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_FLOW_CONTROL)); + TU_ASSERT(ftdi_change_speed(p_cdc, cdch_internal_control_complete, CONFIG_FTDI_FLOW_CONTROL)); break; #else TU_ATTR_FALLTHROUGH; @@ -1342,15 +1337,14 @@ static bool ftdi_proccess_set_config(tuh_xfer_t *xfer) { case CONFIG_FTDI_MODEM_CTRL: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(ftdi_update_mctrl(p_cdc, ftdi_internal_control_complete, CONFIG_FTDI_COMPLETE)); + TU_ASSERT(ftdi_set_modem_ctrl(p_cdc, cdch_process_set_config, CONFIG_FTDI_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; #endif case CONFIG_FTDI_COMPLETE: - set_config_complete(idx, 0, true); + set_config_complete(p_cdc, 0, true); break; default: @@ -1754,12 +1748,9 @@ static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui return open_ep_stream_pair(p_cdc, desc_ep); } -static bool cp210x_process_set_config(tuh_xfer_t *xfer) { +static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); const uintptr_t state = xfer->user_data; - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); switch (state) { case CONFIG_CP210X_IFC_ENABLE: @@ -1796,7 +1787,7 @@ static bool cp210x_process_set_config(tuh_xfer_t *xfer) { #endif case CONFIG_CP210X_COMPLETE: - set_config_complete(idx, 0, true); + set_config_complete(p_cdc, 0, true); break; default: @@ -2018,13 +2009,10 @@ static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, ui return true; } -static bool ch34x_process_set_config(tuh_xfer_t *xfer) { - const uintptr_t state = xfer->user_data; - uint8_t const itf_num = 0; // CH34x has only interface 0, since wIndex is used as payload - uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t *p_cdc = get_itf(idx); +static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { uint8_t buffer[2];// TODO remove - TU_ASSERT(p_cdc && xfer->result == XFER_RESULT_SUCCESS); + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); + const uintptr_t state = xfer->user_data; switch (state) { case CONFIG_CH34X_READ_VERSION: @@ -2074,7 +2062,7 @@ static bool ch34x_process_set_config(tuh_xfer_t *xfer) { #endif case CONFIG_CH34X_COMPLETE: - set_config_complete(idx, 0, true); + set_config_complete(p_cdc, 0, true); break; default: @@ -2410,18 +2398,13 @@ static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui return true; } -static bool pl2303_process_set_config(tuh_xfer_t *xfer) { - const uintptr_t state = xfer->user_data; - // PL2303 has only interface 0, because wIndex is used as payload and not for bInterfaceNumber - uint8_t const itf_num = 0; - uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t *p_cdc = get_itf(idx); +static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { // state CONFIG_PL2303_READ1 may have no success due to expected stall by pl2303_supports_hx_status() + const uintptr_t state = xfer->user_data; + TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS || state == CONFIG_PL2303_READ1); uint8_t buf = 0; pl2303_type_t type; - TU_ASSERT(p_cdc && (xfer->result == XFER_RESULT_SUCCESS || state == CONFIG_PL2303_READ1)); - switch (state) { // from here sequence overtaken from Linux Kernel function pl2303_startup() case CONFIG_PL2303_DETECT_TYPE: @@ -2618,7 +2601,7 @@ static bool pl2303_process_set_config(tuh_xfer_t *xfer) { // break; case CONFIG_PL2303_COMPLETE: - set_config_complete(idx, 0, true); + set_config_complete(p_cdc, 0, true); break; default: From 470e12febca6e371de03120508ef44db28e8501d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 20 Jun 2025 17:25:58 +0700 Subject: [PATCH 239/382] refactor, add cdch_internal_control_complete() --- src/class/cdc/cdc_host.c | 233 ++++++++++++++++----------------------- 1 file changed, 95 insertions(+), 138 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index f36487758..1786f7815 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -119,6 +119,7 @@ static void cdch_internal_control_complete(tuh_xfer_t *xfer); //------------- ACM prototypes -------------// static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void acm_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); static bool acm_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -144,8 +145,7 @@ static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIS static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void acm_internal_control_complete(tuh_xfer_t *xfer); -static void cp210x_internal_control_complete(tuh_xfer_t *xfer); +static void cp210x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); static bool cp210x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool cp210x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -159,7 +159,7 @@ static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST} static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void ch34x_internal_control_complete(tuh_xfer_t *xfer); +static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); static bool ch34x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ch34x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -174,7 +174,7 @@ static const pl2303_type_data_t pl2303_type_data[PL2303_TYPE_COUNT] = {PL2303_TY static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void pl2303_internal_control_complete(tuh_xfer_t *xfer); +static void pl2303_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); static bool pl2303_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool pl2303_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -237,6 +237,8 @@ static const cdch_serial_driver_t serial_drivers[] = { .is_2stage_line_coding = false, .open = acm_open, .process_set_config = acm_process_set_config, + .request_complete = acm_internal_control_complete, + .set_control_line_state = acm_set_control_line_state, .set_baudrate = acm_set_baudrate, .set_data_format = acm_set_data_format, @@ -252,6 +254,7 @@ static const cdch_serial_driver_t serial_drivers[] = { .open = ftdi_open, .process_set_config = ftdi_proccess_set_config, .request_complete = ftdi_internal_control_complete, + .set_control_line_state = ftdi_set_modem_ctrl, .set_baudrate = ftdi_set_baudrate, .set_data_format = ftdi_set_data_format, @@ -267,6 +270,8 @@ static const cdch_serial_driver_t serial_drivers[] = { .is_2stage_line_coding = true, .open = cp210x_open, .process_set_config = cp210x_process_set_config, + .request_complete = cp210x_internal_control_complete, + .set_control_line_state = cp210x_set_modem_ctrl, .set_baudrate = cp210x_set_baudrate, .set_data_format = cp210x_set_data_format, @@ -282,6 +287,8 @@ static const cdch_serial_driver_t serial_drivers[] = { .is_2stage_line_coding = true, .open = ch34x_open, .process_set_config = ch34x_process_set_config, + .request_complete = ch34x_internal_control_complete, + .set_control_line_state = ch34x_set_modem_ctrl, .set_baudrate = ch34x_set_baudrate, .set_data_format = ch34x_set_data_format, @@ -297,6 +304,8 @@ static const cdch_serial_driver_t serial_drivers[] = { .is_2stage_line_coding = false, .open = pl2303_open, .process_set_config = pl2303_process_set_config, + .request_complete = pl2303_internal_control_complete, + .set_control_line_state = pl2303_set_modem_ctrl, .set_baudrate = pl2303_set_baudrate, .set_data_format = pl2303_set_data_format, @@ -904,37 +913,28 @@ static void cdch_internal_control_complete(tuh_xfer_t *xfer) { //--------------------------------------------------------------------+ // internal control complete to update state such as line state, encoding -static void acm_internal_control_complete(tuh_xfer_t *xfer) { - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - bool const success = (xfer->result == XFER_RESULT_SUCCESS); +static void acm_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { + TU_VERIFY (xfer->result == XFER_RESULT_SUCCESS,); + const tusb_control_request_t * setup = xfer->setup; - if (success) { - switch (xfer->setup->bRequest) { - case CDC_REQUEST_SET_CONTROL_LINE_STATE: - p_cdc->line.control_state = p_cdc->requested_line.control_state; - break; + switch (setup->bRequest) { + case CDC_REQUEST_SET_CONTROL_LINE_STATE: + p_cdc->line.control_state = p_cdc->requested_line.control_state; + break; - case CDC_REQUEST_SET_LINE_CODING: - p_cdc->line.coding = p_cdc->requested_line.coding; - break; + case CDC_REQUEST_SET_LINE_CODING: + p_cdc->line.coding = p_cdc->requested_line.coding; + break; - default: break; - } - } - - xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { - xfer->complete_cb(xfer); + default: + break; } } static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { TU_VERIFY(p_cdc->acm.capability.support_line_request); - tusb_control_request_t const request = { + const tusb_control_request_t request = { .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_INTERFACE, .type = TUSB_REQ_TYPE_CLASS, @@ -953,7 +953,7 @@ static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t co .ep_addr = 0, .setup = &request, .buffer = NULL, - .complete_cb = complete_cb ? acm_internal_control_complete : NULL, + .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, .user_data = user_data }; @@ -990,7 +990,7 @@ static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ .ep_addr = 0, .setup = &request, .buffer = enum_buf, - .complete_cb = complete_cb ? acm_internal_control_complete : NULL, + .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, .user_data = user_data }; @@ -1178,6 +1178,7 @@ static bool ftdi_set_data_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet // internal control complete to update state such as line state, line_coding static void ftdi_internal_control_complete(cdch_interface_t* p_cdc, tuh_xfer_t *xfer) { + TU_VERIFY(xfer->result == XFER_RESULT_SUCCESS,); const tusb_control_request_t * setup = xfer->setup; if (xfer->result == XFER_RESULT_SUCCESS) { if (setup->bRequest == FTDI_SIO_SET_MODEM_CTRL_REQUEST && @@ -1650,50 +1651,36 @@ static inline bool cp210x_set_mhs(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet //------------- Driver API -------------// // internal control complete to update state such as line state, encoding -static void cp210x_internal_control_complete(tuh_xfer_t *xfer) { - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - bool const success = (xfer->result == XFER_RESULT_SUCCESS); +static void cp210x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { + TU_VERIFY(xfer->result == XFER_RESULT_SUCCESS,); + switch (xfer->setup->bRequest) { + case CP210X_SET_MHS: + p_cdc->line.control_state = p_cdc->requested_line.control_state; + break; - if (success) { - switch (xfer->setup->bRequest) { - case CP210X_SET_MHS: - p_cdc->line.control_state = p_cdc->requested_line.control_state; - break; + case CP210X_SET_LINE_CTL: + p_cdc->line.coding.stop_bits = p_cdc->requested_line.coding.stop_bits; + p_cdc->line.coding.parity = p_cdc->requested_line.coding.parity; + p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits; + break; - case CP210X_SET_LINE_CTL: - p_cdc->line.coding.stop_bits = p_cdc->requested_line.coding.stop_bits; - p_cdc->line.coding.parity = p_cdc->requested_line.coding.parity; - p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits; - break; + case CP210X_SET_BAUDRATE: + p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; + break; - case CP210X_SET_BAUDRATE: - p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; - break; - - default: break; - } - } - - xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { - xfer->complete_cb(xfer); + default: break; } } static bool cp210x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(cp210x_set_baudrate_request(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); - + TU_ASSERT(cp210x_set_baudrate_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } static bool cp210x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(cp210x_set_line_ctl(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); - + TU_ASSERT(cp210x_set_line_ctl(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } @@ -1701,7 +1688,7 @@ static void cp210x_set_line_coding_stage1_complete(tuh_xfer_t *xfer) { uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); set_line_coding_stage1_complete(xfer, itf_num, cp210x_set_line_ctl, // control request function to set data format - cp210x_internal_control_complete); // control complete function to be called after request + cdch_internal_control_complete); // control complete function to be called after request } // 2 stages: set baudrate (stage1) + set data format (stage2) @@ -1710,14 +1697,13 @@ static bool cp210x_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t comple cp210x_set_baudrate_request, // control request function to set baudrate cp210x_set_line_ctl, // control request function to set data format cp210x_set_line_coding_stage1_complete, // function to be called after stage 1 completed - cp210x_internal_control_complete, // control complete function to be called after request + cdch_internal_control_complete, // control complete function to be called after request complete_cb, user_data); } static bool cp210x_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(cp210x_set_mhs(p_cdc, complete_cb ? cp210x_internal_control_complete : NULL, user_data)); - + TU_ASSERT(cp210x_set_mhs(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } @@ -1761,7 +1747,7 @@ static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(cp210x_set_baudrate_request(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_SET_LINE_CTL)); + TU_ASSERT(cp210x_set_baudrate_request(p_cdc, cdch_internal_control_complete, CONFIG_CP210X_SET_LINE_CTL)); break; #else TU_ATTR_FALLTHROUGH; @@ -1770,7 +1756,7 @@ static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_CP210X_SET_LINE_CTL: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(cp210x_set_line_ctl(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_SET_DTR_RTS)); + TU_ASSERT(cp210x_set_line_ctl(p_cdc, cdch_internal_control_complete, CONFIG_CP210X_SET_DTR_RTS)); break; #else TU_ATTR_FALLTHROUGH; @@ -1780,7 +1766,7 @@ static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(cp210x_set_mhs(p_cdc, cp210x_internal_control_complete, CONFIG_CP210X_COMPLETE)); + TU_ASSERT(cp210x_set_mhs(p_cdc, cdch_internal_control_complete, CONFIG_CP210X_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; @@ -1891,60 +1877,45 @@ static bool ch34x_modem_ctrl_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t comp //------------- Driver API -------------// // internal control complete to update state such as line state, encoding -static void ch34x_internal_control_complete(tuh_xfer_t *xfer) { - // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber - uint8_t const itf_num = 0; - uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - bool const success = (xfer->result == XFER_RESULT_SUCCESS); +static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { + TU_VERIFY(xfer->result == XFER_RESULT_SUCCESS,); + switch (xfer->setup->bRequest) { + case CH34X_REQ_WRITE_REG: + // register write request + switch (tu_le16toh(xfer->setup->wValue)) { + case CH34X_REG16_DIVISOR_PRESCALER: + // baudrate + p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; + break; - if (success) { - switch (xfer->setup->bRequest) { - case CH34X_REQ_WRITE_REG: - // register write request - switch (tu_le16toh(xfer->setup->wValue)) { - case CH34X_REG16_DIVISOR_PRESCALER: - // baudrate - p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; - break; + case CH32X_REG16_LCR2_LCR: + // data format + p_cdc->line.coding.stop_bits = p_cdc->requested_line.coding.stop_bits; + p_cdc->line.coding.parity = p_cdc->requested_line.coding.parity; + p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits; + break; - case CH32X_REG16_LCR2_LCR: - // data format - p_cdc->line.coding.stop_bits = p_cdc->requested_line.coding.stop_bits; - p_cdc->line.coding.parity = p_cdc->requested_line.coding.parity; - p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits; - break; + default: break; + } + break; - default: break; - } - break; + case CH34X_REQ_MODEM_CTRL: + p_cdc->line.control_state = p_cdc->requested_line.control_state; + break; - case CH34X_REQ_MODEM_CTRL: - p_cdc->line.control_state = p_cdc->requested_line.control_state; - break; - - default: break; - } - } - - xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { - xfer->complete_cb(xfer); + default: break; } } static bool ch34x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(ch34x_write_reg_data_format(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); - + TU_ASSERT(ch34x_write_reg_data_format(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } static bool ch34x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); - + TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } @@ -1953,7 +1924,7 @@ static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t *xfer) { uint8_t const itf_num = 0; set_line_coding_stage1_complete(xfer, itf_num, ch34x_write_reg_data_format, // control request function to set data format - ch34x_internal_control_complete); // control complete function to be called after request + cdch_internal_control_complete); // control complete function to be called after request } // 2 stages: set baudrate (stage1) + set data format (stage2) @@ -1962,14 +1933,13 @@ static bool ch34x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t comple ch34x_write_reg_baudrate, // control request function to set baudrate ch34x_write_reg_data_format, // control request function to set data format ch34x_set_line_coding_stage1_complete, // function to be called after stage 1 completed - ch34x_internal_control_complete, // control complete function to be called after request + cdch_internal_control_complete, // control complete function to be called after request complete_cb, user_data); } static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, complete_cb ? ch34x_internal_control_complete : NULL, user_data)); - + TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } @@ -2055,7 +2025,7 @@ static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, ch34x_internal_control_complete, CONFIG_CH34X_COMPLETE)); + TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, cdch_internal_control_complete, CONFIG_CH34X_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; @@ -2293,41 +2263,28 @@ static inline int pl2303_clear_halt(cdch_interface_t *p_cdc, uint8_t endp, tuh_x //------------- Driver API -------------// // internal control complete to update state such as line state, encoding -static void pl2303_internal_control_complete(tuh_xfer_t *xfer) { - // PL2303 has only interface 0, because wIndex is used as payload and not for bInterfaceNumber - uint8_t const itf_num = 0; - uint8_t idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - bool const success = (xfer->result == XFER_RESULT_SUCCESS); - - if (success) { - if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && - xfer->setup->bmRequestType == PL2303_SET_LINE_REQUEST_TYPE) { - p_cdc->line.coding = p_cdc->requested_line.coding; - } - if (xfer->setup->bRequest == PL2303_SET_CONTROL_REQUEST && - xfer->setup->bmRequestType == PL2303_SET_CONTROL_REQUEST_TYPE) { - p_cdc->line.control_state = p_cdc->requested_line.control_state; - } +static void pl2303_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { + TU_VERIFY(xfer->result == XFER_RESULT_SUCCESS,); + if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && + xfer->setup->bmRequestType == PL2303_SET_LINE_REQUEST_TYPE) { + p_cdc->line.coding = p_cdc->requested_line.coding; } - - xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { - xfer->complete_cb(xfer); + if (xfer->setup->bRequest == PL2303_SET_CONTROL_REQUEST && + xfer->setup->bmRequestType == PL2303_SET_CONTROL_REQUEST_TYPE) { + p_cdc->line.control_state = p_cdc->requested_line.control_state; } } static bool pl2303_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); + TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } static bool pl2303_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { p_cdc->requested_line.coding.bit_rate = p_cdc->line.coding.bit_rate; p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); + TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } @@ -2336,14 +2293,14 @@ static bool pl2303_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ p_cdc->requested_line.coding.parity = p_cdc->line.coding.parity; p_cdc->requested_line.coding.data_bits = p_cdc->line.coding.data_bits; p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); + TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } static bool pl2303_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // PL2303 has the same bit coding p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(pl2303_set_control_lines(p_cdc, complete_cb ? pl2303_internal_control_complete : NULL, user_data)); + TU_ASSERT(pl2303_set_control_lines(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); return true; } @@ -2557,7 +2514,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_LINE_CODING: #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(pl2303_set_line_request(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_MODEM_CONTROL)); + TU_ASSERT(pl2303_set_line_request(p_cdc, cdch_internal_control_complete, CONFIG_PL2303_MODEM_CONTROL)); break; #else TU_ATTR_FALLTHROUGH; @@ -2566,7 +2523,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_MODEM_CONTROL: #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT(pl2303_set_control_lines(p_cdc, pl2303_internal_control_complete, CONFIG_PL2303_COMPLETE)); + TU_ASSERT(pl2303_set_control_lines(p_cdc, cdch_internal_control_complete, CONFIG_PL2303_COMPLETE)); break; #else TU_ATTR_FALLTHROUGH; From 4ae433fa6ef451cccb2b09aa3748978b46aade5f Mon Sep 17 00:00:00 2001 From: milek7 Date: Wed, 25 Jun 2025 03:35:40 +0200 Subject: [PATCH 240/382] stm32_fsdev: Allow configuring single-buffered isochronous endpoints. Controlled by the embedder defining CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP in tusb_config.h. If hardware does have SBUF_ISO bit it will use only one half of endpoint pair register. --- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 47 +++++++++++++++---- src/portable/st/stm32_fsdev/fsdev_ch32.h | 5 ++ src/portable/st/stm32_fsdev/fsdev_stm32.h | 38 +++++++++++++++ 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index ef58957bb..ad733b16a 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -331,8 +331,13 @@ static void handle_ctr_rx(uint32_t ep_id) { xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, TUSB_DIR_OUT); uint8_t buf_id; - if (is_iso) { - buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; // ISO are double buffered +#if FSDEV_USE_SBUF_ISO == 0 + bool const dbl_buf = is_iso; +#else + bool const dbl_buf = false; +#endif + if (dbl_buf) { + buf_id = (ep_reg & USB_EP_DTOG_RX) ? 0 : 1; } else { buf_id = BTABLE_BUF_RX; } @@ -527,10 +532,16 @@ static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type) return i; } +#if FSDEV_USE_SBUF_ISO == 0 + bool const dbl_buf = ep_type == TUSB_XFER_ISOCHRONOUS; +#else + bool const dbl_buf = false; +#endif + // If EP of current direction is not allocated - // Except for ISO endpoint, both direction should be free + // For double-buffered mode both directions needs to be free if (!ep_alloc_status[i].allocated[dir] && - (ep_type != TUSB_XFER_ISOCHRONOUS || !ep_alloc_status[i].allocated[dir ^ 1])) { + (!dbl_buf || !ep_alloc_status[i].allocated[dir ^ 1])) { // Check if EP number is the same if (ep_alloc_status[i].ep_num == 0xFF || ep_alloc_status[i].ep_num == epnum) { // One EP pair has to be the same type @@ -652,9 +663,7 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet uint8_t const dir = tu_edpt_dir(ep_addr); uint8_t const ep_idx = dcd_ep_alloc(ep_addr, TUSB_XFER_ISOCHRONOUS); - /* Create a packet memory buffer area. Enable double buffering for devices with 2048 bytes PMA, - for smaller devices double buffering occupy too much space. */ -#if FSDEV_PMA_SIZE > 1024u +#if CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP != 0 uint32_t pma_addr = dcd_pma_alloc(largest_packet_size, true); uint16_t pma_addr2 = pma_addr >> 16; #else @@ -662,8 +671,12 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet uint16_t pma_addr2 = pma_addr; #endif +#if FSDEV_USE_SBUF_ISO == 0 btable_set_addr(ep_idx, 0, pma_addr); btable_set_addr(ep_idx, 1, pma_addr2); +#else + btable_set_addr(ep_idx, dir == TUSB_DIR_IN ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr); +#endif xfer_ctl_t* xfer = xfer_ctl_ptr(ep_num, dir); xfer->ep_idx = ep_idx; @@ -684,10 +697,23 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const *desc_ep) uint32_t ep_reg = ep_read(ep_idx) & ~USB_EPREG_MASK; ep_reg |= tu_edpt_number(ep_addr) | USB_EP_ISOCHRONOUS | USB_EP_CTR_TX | USB_EP_CTR_RX; +#if FSDEV_USE_SBUF_ISO != 0 + ep_reg |= USB_EP_KIND; + + ep_change_status(&ep_reg, dir, EP_STAT_DISABLED); + ep_change_dtog(&ep_reg, dir, 0); + + if (dir == TUSB_DIR_IN) { + ep_reg &= ~(USB_EPRX_STAT | USB_EP_DTOG_RX); + } else { + ep_reg &= ~(USB_EPTX_STAT | USB_EP_DTOG_TX); + } +#else ep_change_status(&ep_reg, TUSB_DIR_IN, EP_STAT_DISABLED); ep_change_status(&ep_reg, TUSB_DIR_OUT, EP_STAT_DISABLED); ep_change_dtog(&ep_reg, dir, 0); ep_change_dtog(&ep_reg, (tusb_dir_t)(1 - dir), 1); +#endif ep_write(ep_idx, ep_reg, true); @@ -702,7 +728,12 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) { bool const is_iso = ep_is_iso(ep_reg); uint8_t buf_id; - if (is_iso) { +#if FSDEV_USE_SBUF_ISO == 0 + bool const dbl_buf = is_iso; +#else + bool const dbl_buf = false; +#endif + if (dbl_buf) { buf_id = (ep_reg & USB_EP_DTOG_TX) ? 1 : 0; } else { buf_id = BTABLE_BUF_TX; diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h index 518197c47..ceebb6dab 100644 --- a/src/portable/st/stm32_fsdev/fsdev_ch32.h +++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h @@ -54,9 +54,14 @@ #endif #define FSDEV_PMA_SIZE (512u) +#define FSDEV_USE_SBUF_ISO 0 #define FSDEV_REG_BASE (APB1PERIPH_BASE + 0x00005C00UL) #define FSDEV_PMA_BASE (APB1PERIPH_BASE + 0x00006000UL) +#ifndef CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP + #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 0 +#endif + /**************************** ISTR interrupt events *************************/ #define USB_ISTR_CTR ((uint16_t)0x8000U) /*!< Correct TRansfer (clear-only bit) */ #define USB_ISTR_PMAOVR ((uint16_t)0x4000U) /*!< DMA OVeR/underrun (clear-only bit) */ diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index ccf31e035..770baa05a 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -36,6 +36,7 @@ #include "stm32f0xx.h" #define FSDEV_PMA_SIZE (1024u) #define FSDEV_REG_BASE USB_BASE + #define FSDEV_HAS_SBUF_ISO 0 // F0x2 models are crystal-less // All have internal D+ pull-up // 070RB: 2 x 16 bits/word memory LPM Support, BCD Support @@ -44,6 +45,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32F1 #include "stm32f1xx.h" #define FSDEV_PMA_SIZE (512u) + #define FSDEV_HAS_SBUF_ISO 0 // NO internal Pull-ups // *B, and *C: 2 x 16 bits/word @@ -55,6 +57,7 @@ defined(STM32F373xC) #include "stm32f3xx.h" #define FSDEV_PMA_SIZE (512u) + #define FSDEV_HAS_SBUF_ISO 0 // NO internal Pull-ups // *B, and *C: 1 x 16 bits/word // PMA dedicated to USB (no sharing with CAN) @@ -64,6 +67,7 @@ defined(STM32F303xD) || defined(STM32F303xE) #include "stm32f3xx.h" #define FSDEV_PMA_SIZE (1024u) + #define FSDEV_HAS_SBUF_ISO 0 // NO internal Pull-ups // *6, *8, *D, and *E: 2 x 16 bits/word LPM Support // When CAN clock is enabled, USB can use first 768 bytes ONLY. @@ -71,18 +75,22 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32L0 #include "stm32l0xx.h" #define FSDEV_PMA_SIZE (1024u) + #define FSDEV_HAS_SBUF_ISO 0 #elif CFG_TUSB_MCU == OPT_MCU_STM32L1 #include "stm32l1xx.h" #define FSDEV_PMA_SIZE (512u) + #define FSDEV_HAS_SBUF_ISO 0 #elif CFG_TUSB_MCU == OPT_MCU_STM32G4 #include "stm32g4xx.h" #define FSDEV_PMA_SIZE (1024u) + #define FSDEV_HAS_SBUF_ISO 0 #elif CFG_TUSB_MCU == OPT_MCU_STM32G0 #include "stm32g0xx.h" #define FSDEV_PMA_SIZE (2048u) + #define FSDEV_HAS_SBUF_ISO 1 #define USB USB_DRD_FS #define USB_EP_CTR_RX USB_EP_VTRX @@ -107,6 +115,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32C0 #include "stm32c0xx.h" #define FSDEV_PMA_SIZE (2048u) + #define FSDEV_HAS_SBUF_ISO 1 #define USB USB_DRD_FS #define USB_EP_CTR_RX USB_CHEP_VTRX #define USB_EP_CTR_TX USB_CHEP_VTTX @@ -121,6 +130,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32H5 #include "stm32h5xx.h" #define FSDEV_PMA_SIZE (2048u) + #define FSDEV_HAS_SBUF_ISO 1 #define USB USB_DRD_FS #define USB_EP_CTR_RX USB_EP_VTRX @@ -145,16 +155,19 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32WB #include "stm32wbxx.h" #define FSDEV_PMA_SIZE (1024u) + #define FSDEV_HAS_SBUF_ISO 0 /* ST provided header has incorrect value of USB_PMAADDR */ #define FSDEV_PMA_BASE USB1_PMAADDR #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 #include "stm32l4xx.h" #define FSDEV_PMA_SIZE (1024u) + #define FSDEV_HAS_SBUF_ISO 0 #elif CFG_TUSB_MCU == OPT_MCU_STM32L5 #include "stm32l5xx.h" #define FSDEV_PMA_SIZE (1024u) + #define FSDEV_HAS_SBUF_ISO 0 #ifndef USB_PMAADDR #define USB_PMAADDR (USB_BASE + (USB_PMAADDR_NS - USB_BASE_NS)) @@ -163,6 +176,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 #include "stm32u5xx.h" #define FSDEV_PMA_SIZE (2048u) + #define FSDEV_HAS_SBUF_ISO 1 #define USB USB_DRD_FS #define USB_EP_CTR_RX USB_EP_VTRX @@ -187,6 +201,7 @@ #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 #include "stm32u0xx.h" #define FSDEV_PMA_SIZE (2048u) + #define FSDEV_HAS_SBUF_ISO 1 #define USB USB_DRD_FS #define USB_EP_CTR_RX USB_EP_VTRX @@ -248,6 +263,29 @@ #define USB_ISTR_ALL_EVENTS (USB_ISTR_PMAOVR | USB_ISTR_ERR | USB_ISTR_WKUP | USB_ISTR_SUSP | \ USB_ISTR_RESET | USB_ISTR_SOF | USB_ISTR_ESOF | USB_ISTR_L1REQ_FORCED ) +#ifndef FSDEV_HAS_SBUF_ISO + #error "FSDEV_HAS_SBUF_ISO not defined" +#endif + +#ifndef CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP + // Defaults to double-buffered isochronous endpoints on devices with >1KB PMA + #if FSDEV_PMA_SIZE > 1024u + #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 1 + #else + #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 0 + #endif +#endif + +#if FSDEV_HAS_SBUF_ISO != 0 && CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP == 0 + // If hardware has SBUF_ISO bit single-buffered endpoints consume only + // one half of endpoint pair register. + #define FSDEV_USE_SBUF_ISO 1 +#else + // Otherwise it consumes entire endpoint pair but we can at least save + // memory by configuring the same buffer twice. + #define FSDEV_USE_SBUF_ISO 0 +#endif + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ From 2843eb405252ba4f8475c86d346b95547fb4020c Mon Sep 17 00:00:00 2001 From: milek7 Date: Thu, 26 Jun 2025 00:03:25 +0200 Subject: [PATCH 241/382] audio_device: Fix data IN endpoints with implicit feedback --- src/class/audio/audio_device.c | 37 ++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 11a3d4a73..a877dc900 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -1003,20 +1003,22 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint ep_fb = desc_ep->bEndpointAddress; } #endif - // Data EP - if (desc_ep->bmAttributes.usage == 0) { - if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { #if CFG_TUD_AUDIO_ENABLE_EP_IN - ep_in = desc_ep->bEndpointAddress; - ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size); - #endif - } else { - #if CFG_TUD_AUDIO_ENABLE_EP_OUT - ep_out = desc_ep->bEndpointAddress; - ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size); - #endif - } + // Data or data with implicit feedback IN EP + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN + && (desc_ep->bmAttributes.usage == 0 || desc_ep->bmAttributes.usage == 2)) { + ep_in = desc_ep->bEndpointAddress; + ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size); } + #endif + #if CFG_TUD_AUDIO_ENABLE_EP_OUT + // Data OUT EP + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_OUT + && desc_ep->bmAttributes.usage == 0) { + ep_out = desc_ep->bEndpointAddress; + ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size); + } + #endif } } @@ -1052,10 +1054,10 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) { tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) { - if (desc_ep->bmAttributes.usage == 0) { - if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { - _audiod_fct[i].interval_tx = desc_ep->bInterval; - } + // For data or data with implicit feedback IN EP + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN + && (desc_ep->bmAttributes.usage == 0 || desc_ep->bmAttributes.usage == 2)) { + _audiod_fct[i].interval_tx = desc_ep->bInterval; } } } else if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL) { @@ -1227,7 +1229,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p usbd_edpt_clear_stall(rhport, ep_addr); #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 0x00)// Check if usage is data EP + // For data or data with implicit feedback IN EP + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && (desc_ep->bmAttributes.usage == 0 || desc_ep->bmAttributes.usage == 2)) { // Save address audio->ep_in = ep_addr; From 8b5d703f74153c75dd9e4cfb224dbe74e4e262fa Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Jun 2025 15:57:18 +0700 Subject: [PATCH 242/382] major refactor to generalize cdch serial driver - add common 2 stage set line coding for driver without direct set_line_coding support e.g ftdi, cp210x, ch34x - add common cdch_process_line_state_on_enum() to handle cfg line state on enum e.g CFG_TUH_CDC_LINE_CONTROL/CODING_ON_ENUM - refactor cdch_internal_control_complete and user_complete_cb to be managed by tuh_cdc_ API instead of serial driver --- src/class/cdc/cdc_host.c | 663 +++++++++++++---------------------- src/class/cdc/serial/ch34x.h | 4 +- 2 files changed, 246 insertions(+), 421 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 1786f7815..7926aa9fc 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -45,12 +45,9 @@ #define CFG_TUH_CDC_LOG_LEVEL 1 #endif -#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) -#define TU_LOG_CDC(_cdc, _format, ...) TU_LOG_DRV("[:%u:%u] CDCh %s " _format "\r\n", _cdc->daddr, _cdc->bInterfaceNumber, \ - serial_drivers[_cdc->serial_drid].name, ##__VA_ARGS__) - -// Driver that need to set line coding in two stages: baudrate then data format. -#define DRIVER_2STAGE_SET_LINE_CODING (CFG_TUH_CDC_FTDI || CFG_TUH_CDC_CP210X || CFG_TUH_CDC_CH34X) +#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) +#define TU_LOG_CDC(_cdc, _format, ...) TU_LOG_DRV("[:%u:%u] CDCh %s " _format "\r\n", _cdc->daddr, _cdc->bInterfaceNumber, \ + serial_drivers[_cdc->serial_drid].name, ##__VA_ARGS__) //--------------------------------------------------------------------+ // Host CDC Interface @@ -73,10 +70,6 @@ typedef struct { tuh_xfer_cb_t user_complete_cb; // required since we handle request internally first - #if DRIVER_2STAGE_SET_LINE_CODING - tuh_xfer_cb_t requested_complete_cb; - #endif - union { struct { cdc_acm_capability_t capability; @@ -114,7 +107,10 @@ CFG_TUH_MEM_SECTION static cdch_epbuf_t cdch_epbuf[CFG_TUH_CDC]; // General driver static void cdch_process_set_config(tuh_xfer_t *xfer); +static void cdch_process_line_state_on_enum(tuh_xfer_t *xfer); // invoked after set config is processed static void cdch_internal_control_complete(tuh_xfer_t *xfer); +static void cdch_set_line_coding_stage1_baudrate_complete(tuh_xfer_t *xfer); +static void cdch_set_line_coding_stage2_data_format_complete(tuh_xfer_t *xfer); //------------- ACM prototypes -------------// static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); @@ -135,7 +131,6 @@ static void ftdi_internal_control_complete(cdch_interface_t* p_cdc, tuh_xfer_t * static bool ftdi_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ftdi_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ftdi_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif @@ -149,7 +144,6 @@ static void cp210x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t static bool cp210x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool cp210x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool cp210x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif @@ -163,7 +157,6 @@ static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t static bool ch34x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ch34x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ch34x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif @@ -210,8 +203,6 @@ typedef bool (*serial_driver_func_t)(cdch_interface_t * p_cdc, tuh_xfer_cb_t com typedef struct { uint16_t const (*vid_pid_list)[2]; uint16_t const vid_pid_count; - bool is_2stage_line_coding; // true if driver requires to set baudrate then data format separately - bool (*const open)(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); bool (*const process_set_config)(cdch_interface_t * p_cdc, tuh_xfer_t * xfer); void (*const request_complete)(cdch_interface_t * p_cdc, tuh_xfer_t * xfer); // internal request complete handler to update line state @@ -234,7 +225,6 @@ static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = NULL, .vid_pid_count = 0, - .is_2stage_line_coding = false, .open = acm_open, .process_set_config = acm_process_set_config, .request_complete = acm_internal_control_complete, @@ -250,15 +240,13 @@ static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = ftdi_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(ftdi_vid_pid_list), - .is_2stage_line_coding = true, .open = ftdi_open, .process_set_config = ftdi_proccess_set_config, .request_complete = ftdi_internal_control_complete, - .set_control_line_state = ftdi_set_modem_ctrl, .set_baudrate = ftdi_set_baudrate, .set_data_format = ftdi_set_data_format, - .set_line_coding = ftdi_set_line_coding, + .set_line_coding = NULL, // 2 stage set line coding DRIVER_NAME_DECLARE("FTDI") }, #endif @@ -267,15 +255,13 @@ static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = cp210x_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(cp210x_vid_pid_list), - .is_2stage_line_coding = true, .open = cp210x_open, .process_set_config = cp210x_process_set_config, .request_complete = cp210x_internal_control_complete, - .set_control_line_state = cp210x_set_modem_ctrl, .set_baudrate = cp210x_set_baudrate, .set_data_format = cp210x_set_data_format, - .set_line_coding = cp210x_set_line_coding, + .set_line_coding = NULL, // 2 stage set line coding DRIVER_NAME_DECLARE("CP210x") }, #endif @@ -284,7 +270,6 @@ static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = ch34x_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(ch34x_vid_pid_list), - .is_2stage_line_coding = true, .open = ch34x_open, .process_set_config = ch34x_process_set_config, .request_complete = ch34x_internal_control_complete, @@ -292,7 +277,7 @@ static const cdch_serial_driver_t serial_drivers[] = { .set_control_line_state = ch34x_set_modem_ctrl, .set_baudrate = ch34x_set_baudrate, .set_data_format = ch34x_set_data_format, - .set_line_coding = ch34x_set_line_coding, + .set_line_coding = NULL, // 2 stage set line coding DRIVER_NAME_DECLARE("CH34x") }, #endif @@ -301,11 +286,9 @@ static const cdch_serial_driver_t serial_drivers[] = { { .vid_pid_list = pl2303_vid_pid_list, .vid_pid_count = TU_ARRAY_SIZE(pl2303_vid_pid_list), - .is_2stage_line_coding = false, .open = pl2303_open, .process_set_config = pl2303_process_set_config, .request_complete = pl2303_internal_control_complete, - .set_control_line_state = pl2303_set_modem_ctrl, .set_baudrate = pl2303_set_baudrate, .set_data_format = pl2303_set_data_format, @@ -474,28 +457,24 @@ bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t * line_coding) uint32_t tuh_cdc_write(uint8_t idx, void const * buffer, uint32_t bufsize) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write(p_cdc->daddr, &p_cdc->stream.tx, buffer, bufsize); } uint32_t tuh_cdc_write_flush(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write_xfer(p_cdc->daddr, &p_cdc->stream.tx); } bool tuh_cdc_write_clear(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_clear(&p_cdc->stream.tx); } uint32_t tuh_cdc_write_available(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write_available(p_cdc->daddr, &p_cdc->stream.tx); } @@ -506,21 +485,18 @@ uint32_t tuh_cdc_write_available(uint8_t idx) { uint32_t tuh_cdc_read (uint8_t idx, void * buffer, uint32_t bufsize) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_read(p_cdc->daddr, &p_cdc->stream.rx, buffer, bufsize); } uint32_t tuh_cdc_read_available(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_read_available(&p_cdc->stream.rx); } bool tuh_cdc_peek(uint8_t idx, uint8_t * ch) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_peek(&p_cdc->stream.rx, ch); } @@ -537,105 +513,40 @@ bool tuh_cdc_read_clear (uint8_t idx) { // Control Endpoint API //--------------------------------------------------------------------+ -#if DRIVER_2STAGE_SET_LINE_CODING - -// set line coding using sequence with 2 stages: set baudrate (stage1) + set data format (stage2) -static bool set_line_coding_sequence( - cdch_interface_t * p_cdc, - serial_driver_func_t set_baudrate, - serial_driver_func_t set_data_format, - tuh_xfer_cb_t set_line_coding_stage1_complete, // function to be called after stage 1 completed - tuh_xfer_cb_t internal_control_complete, // control complete function to be called after request - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - if (complete_cb) { - // non-blocking - // stage 1 set baudrate - p_cdc->requested_complete_cb = complete_cb; // store complete_cb to be used in set_line_coding_stage1_complete() - p_cdc->user_complete_cb = set_line_coding_stage1_complete; - return set_baudrate(p_cdc, internal_control_complete, user_data); - } else { - // blocking sequence - // stage 1 set baudrate - xfer_result_t result = XFER_RESULT_INVALID; // use local result, because user_data ptr may be NULL - bool ret = set_baudrate(p_cdc, NULL, (uintptr_t) &result); - - if (user_data) { - *((xfer_result_t *) user_data) = result; - } - - TU_ASSERT(ret); - TU_VERIFY(result == XFER_RESULT_SUCCESS); - - // overtake baudrate after successful request - p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; - - // stage 2 set data format - result = XFER_RESULT_INVALID; - ret = set_data_format(p_cdc, NULL, (uintptr_t) &result); - - if (user_data) { - *((xfer_result_t *) user_data) = result; - } - - TU_ASSERT(ret); - return (result == XFER_RESULT_SUCCESS); - // the overtaking of remaining requested_line_coding will be done in tuh_cdc_set_line_coding() - } -} - -static void set_line_coding_stage1_complete( - tuh_xfer_t * xfer, uint8_t const itf_num, - // control request function to set data format - bool (*set_data_format_request)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data), - // control complete function to be called after request - void (*internal_control_complete)(tuh_xfer_t * xfer)) { - uint8_t const idx = tuh_cdc_itf_get_index(xfer->daddr, itf_num); - cdch_interface_t * p_cdc = get_itf(idx); - TU_ASSERT(p_cdc,); - - if (xfer->result == XFER_RESULT_SUCCESS) { - // stage 1 success, continue with stage 2 - p_cdc->user_complete_cb = p_cdc->requested_complete_cb; - set_data_format_request(p_cdc, internal_control_complete, xfer->user_data); - } else { - // stage 1 failed, notify user - xfer->complete_cb = p_cdc->requested_complete_cb; - if (xfer->complete_cb) { - xfer->complete_cb(xfer); - } - } -} -#endif - bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); TU_LOG_CDC(p_cdc, "set control line state dtr = %u rts = %u", p_cdc->requested_line.control_state.dtr, p_cdc->requested_line.control_state.rts); - cdch_serial_driver_t const * driver = &serial_drivers[p_cdc->serial_drid]; + const cdch_serial_driver_t * driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line.control_state.value = (uint8_t) line_state; - const bool ret = driver->set_control_line_state(p_cdc, complete_cb, user_data); - if (ret && !complete_cb) { + p_cdc->user_complete_cb = complete_cb; + TU_VERIFY(driver->set_control_line_state(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); + + if (!complete_cb) { // blocking, update line state if request was successful p_cdc->line.control_state.value = (uint8_t) line_state; } - return ret; + return true; } bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { cdch_interface_t *p_cdc = get_itf(idx); TU_VERIFY(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT); TU_LOG_CDC(p_cdc, "set baudrate %lu", baudrate); - cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; + const cdch_serial_driver_t *driver = &serial_drivers[p_cdc->serial_drid]; + p_cdc->requested_line = p_cdc->line; // keep current line coding p_cdc->requested_line.coding.bit_rate = baudrate; - const bool ret = driver->set_baudrate(p_cdc, complete_cb, user_data); - if (ret && !complete_cb) { + p_cdc->user_complete_cb = complete_cb; + TU_VERIFY(driver->set_baudrate(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); + + if (!complete_cb) { p_cdc->line.coding.bit_rate = baudrate; } - return ret; + return true; } bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, @@ -645,20 +556,24 @@ bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uin TU_LOG_CDC(p_cdc, "set data format %u%c%s", data_bits, CDC_LINE_CODING_PARITY_CHAR(parity), CDC_LINE_CODING_STOP_BITS_TEXT(stop_bits)); - cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; + const cdch_serial_driver_t *driver = &serial_drivers[p_cdc->serial_drid]; + p_cdc->requested_line = p_cdc->line; // keep current line coding p_cdc->requested_line.coding.stop_bits = stop_bits; p_cdc->requested_line.coding.parity = parity; p_cdc->requested_line.coding.data_bits = data_bits; - const bool ret = driver->set_data_format(p_cdc, complete_cb, user_data); + p_cdc->user_complete_cb = complete_cb; + TU_VERIFY(driver->set_data_format(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - if (ret && !complete_cb) { + if (!complete_cb) { + // blocking p_cdc->line.coding.stop_bits = stop_bits; p_cdc->line.coding.parity = parity; p_cdc->line.coding.data_bits = data_bits; } - return ret; + + return true; } bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, @@ -670,16 +585,43 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, CDC_LINE_CODING_PARITY_CHAR(line_coding->parity), CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; - p_cdc->requested_line.coding = *line_coding; - const bool ret = driver->set_line_coding(p_cdc, complete_cb, user_data); + if (driver->set_line_coding) { + // driver support set_line_coding request + TU_VERIFY(driver->set_line_coding(p_cdc, complete_cb, user_data)); - if (ret && !complete_cb) { - p_cdc->line.coding = *line_coding; + if (!complete_cb) { + p_cdc->line.coding = *line_coding; + } + } else { + // driver does not support set_line_coding and need 2 stage to set baudrate and data format separately + if (complete_cb) { + // non-blocking + p_cdc->user_complete_cb = complete_cb; + TU_VERIFY(driver->set_baudrate(p_cdc, cdch_set_line_coding_stage1_baudrate_complete, user_data)); + } else { + // blocking + xfer_result_t result = XFER_RESULT_INVALID; + + TU_VERIFY(driver->set_baudrate(p_cdc, NULL, (uintptr_t) &result)); + if (user_data) { + *((xfer_result_t *) user_data) = result; + } + TU_VERIFY(result == XFER_RESULT_SUCCESS); + p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; // update baudrate + + result = XFER_RESULT_INVALID; + TU_VERIFY(driver->set_data_format(p_cdc, NULL, (uintptr_t) &result)); + if (user_data) { + *((xfer_result_t *) user_data) = result; + } + TU_VERIFY(result == XFER_RESULT_SUCCESS); + p_cdc->line.coding = p_cdc->requested_line.coding; // update data format + } } - return ret; + return true; } //--------------------------------------------------------------------+ @@ -809,60 +751,31 @@ static bool open_ep_stream_pair(cdch_interface_t *p_cdc, tusb_desc_endpoint_t co bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; - cdch_serial_driver_t const *driver_detected = NULL; - // For CDC: only support ACM subclass // Note: Protocol 0xFF can be RNDIS device if (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass) { return acm_open(daddr, itf_desc, max_len); - } else if (SERIAL_DRIVER_COUNT > 1 && - TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { - uint16_t vid, pid; - TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); + } else if (SERIAL_DRIVER_COUNT > 1 && + TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { + uint16_t vid, pid; + TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); - for (size_t dr = 1; dr < SERIAL_DRIVER_COUNT; dr++) { - cdch_serial_driver_t const *driver = &serial_drivers[dr]; - for (size_t i = 0; i < driver->vid_pid_count; i++) { - if (driver->vid_pid_list[i][0] == vid && driver->vid_pid_list[i][1] == pid) { - driver_detected = driver; - break; + for (size_t dr = 1; dr < SERIAL_DRIVER_COUNT; dr++) { + const cdch_serial_driver_t *driver = &serial_drivers[dr]; + for (size_t i = 0; i < driver->vid_pid_count; i++) { + if (driver->vid_pid_list[i][0] == vid && driver->vid_pid_list[i][1] == pid) { + const bool ret = driver->open(daddr, itf_desc, max_len); + TU_LOG_DRV("[:%u:%u] CDCh %s open %s\r\n", daddr, itf_desc->bInterfaceNumber, driver->name, ret ? "OK" : "FAILED"); + return ret; + } + } } - } - if (driver_detected) { - break; - } - } - } - - if (driver_detected) { - const bool ret = driver_detected->open(daddr, itf_desc, max_len); - TU_LOG_DRV("[:%u:%u] CDCh %s open %s\r\n", daddr, itf_desc->bInterfaceNumber, driver_detected->name, ret ? "OK" : "FAILED"); - return ret; - } + } return false; } -static void set_config_complete(cdch_interface_t *p_cdc, uint8_t itf_offset, bool success) { - if (success) { - const uint8_t idx = get_idx_by_ptr(p_cdc); - p_cdc->mounted = true; - if (tuh_cdc_mount_cb) { - tuh_cdc_mount_cb(idx); - } - // Prepare for incoming data - tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); - } else { - // clear the interface entry - p_cdc->daddr = 0; - p_cdc->bInterfaceNumber = 0; - } - - // notify usbh that driver enumeration is complete - usbh_driver_set_config_complete(p_cdc->daddr, p_cdc->bInterfaceNumber + itf_offset); -} - bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { tusb_control_request_t request; request.wIndex = tu_htole16((uint16_t) itf_num); @@ -882,24 +795,100 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { return true; } +static void set_config_complete(cdch_interface_t *p_cdc, uint8_t itf_offset, bool success) { + if (success) { + const uint8_t idx = get_idx_by_ptr(p_cdc); + p_cdc->mounted = true; + if (tuh_cdc_mount_cb) { + tuh_cdc_mount_cb(idx); + } + // Prepare for incoming data + tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); + } else { + // clear the interface entry + p_cdc->daddr = 0; + p_cdc->bInterfaceNumber = 0; + } + + // notify usbh that driver enumeration is complete + usbh_driver_set_config_complete(p_cdc->daddr, p_cdc->bInterfaceNumber + itf_offset); +} static void cdch_process_set_config(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf_by_xfer(xfer); TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); TU_LOG_DRV(" state = %u\r\n", xfer->user_data); + const cdch_serial_driver_t *driver = &serial_drivers[p_cdc->serial_drid]; - if (!serial_drivers[p_cdc->serial_drid].process_set_config(p_cdc, xfer)) { + if (!driver->process_set_config(p_cdc, xfer)) { const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; set_config_complete(p_cdc, itf_offset, false); } } +static bool set_line_state_on_enum(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { + enum { + ENUM_SET_LINE_CODING = 0, + ENUM_SET_LINE_CONTROL, + ENUM_SET_LINE_COMPLETE, + }; + const uint8_t idx = get_idx_by_ptr(p_cdc); + const uintptr_t state = xfer->user_data; + + switch (state) { + case ENUM_SET_LINE_CODING: { + #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM + // ch34x already set line coding in serial init + if (p_cdc->serial_drid != SERIAL_DRIVER_CH34X) { + const cdc_line_coding_t line_coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; + TU_ASSERT(tuh_cdc_set_line_coding(idx, &line_coding, + cdch_process_line_state_on_enum, ENUM_SET_LINE_CONTROL)); + break; + } + #endif + TU_ATTR_FALLTHROUGH; + } + + case ENUM_SET_LINE_CONTROL: + #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM + TU_ASSERT(tuh_cdc_set_control_line_state(idx, CFG_TUH_CDC_LINE_CONTROL_ON_ENUM, + cdch_process_line_state_on_enum, ENUM_SET_LINE_COMPLETE)); + break; + #else + TU_ATTR_FALLTHROUGH; + #endif + + case ENUM_SET_LINE_COMPLETE: { + const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; + set_config_complete(p_cdc, itf_offset, true); + break; + } + + default: + return false; + } + + return true; +} + +static void cdch_process_line_state_on_enum(tuh_xfer_t *xfer) { + cdch_interface_t *p_cdc = get_itf_by_xfer(xfer); + TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); + TU_LOG_DRV(" xfer result = %u\r\n", xfer->result); + + if (xfer->result != XFER_RESULT_SUCCESS || !set_line_state_on_enum(p_cdc, xfer)) { + const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; + set_config_complete(p_cdc, itf_offset, false); + } +} + + static void cdch_internal_control_complete(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf_by_xfer(xfer); TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); - TU_LOG_DRV(" request result = %u\r\n", xfer->result); - serial_drivers[p_cdc->serial_drid].request_complete(p_cdc, xfer); + const cdch_serial_driver_t *driver = &serial_drivers[p_cdc->serial_drid]; + driver->request_complete(p_cdc, xfer); // Invoke application callback xfer->complete_cb = p_cdc->user_complete_cb; @@ -908,6 +897,38 @@ static void cdch_internal_control_complete(tuh_xfer_t *xfer) { } } +static void cdch_set_line_coding_stage1_baudrate_complete(tuh_xfer_t *xfer) { + cdch_interface_t *p_cdc = get_itf_by_xfer(xfer); + TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); + TU_LOG_DRV(" stage1 set baudrate result = %u\r\n", xfer->result); + const cdch_serial_driver_t *driver = &serial_drivers[p_cdc->serial_drid]; + + if (xfer->result == XFER_RESULT_SUCCESS) { + p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; // update baudrate + TU_ASSERT(driver->set_data_format(p_cdc, cdch_set_line_coding_stage2_data_format_complete, xfer->user_data),); + } else { + xfer->complete_cb = p_cdc->user_complete_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } + } +} + +static void cdch_set_line_coding_stage2_data_format_complete(tuh_xfer_t *xfer) { + cdch_interface_t *p_cdc = get_itf_by_xfer(xfer); + TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); + TU_LOG_DRV(" stage2 set data format result = %u\r\n", xfer->result); + + if (xfer->result == XFER_RESULT_SUCCESS) { + p_cdc->line.coding = p_cdc->requested_line.coding; // update data format + } + + xfer->complete_cb = p_cdc->user_complete_cb; + if (xfer->complete_cb) { + xfer->complete_cb(xfer); + } +} + //--------------------------------------------------------------------+ // ACM //--------------------------------------------------------------------+ @@ -1000,16 +1021,10 @@ static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ } static bool acm_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->requested_line.coding.bit_rate = p_cdc->line.coding.bit_rate; - return acm_set_line_coding(p_cdc, complete_cb, user_data); } static bool acm_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->requested_line.coding.stop_bits = p_cdc->line.coding.stop_bits; - p_cdc->requested_line.coding.parity = p_cdc->line.coding.parity; - p_cdc->requested_line.coding.data_bits = p_cdc->line.coding.data_bits; - return acm_set_line_coding(p_cdc, complete_cb, user_data); } @@ -1108,7 +1123,6 @@ static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { static bool ftdi_determine_type(cdch_interface_t *p_cdc); static uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc); -static uint8_t ftdi_get_idx(tuh_xfer_t *xfer); //------------- Control Request -------------// @@ -1150,29 +1164,6 @@ static inline bool ftdi_sio_reset(cdch_interface_t *p_cdc, tuh_xfer_cb_t complet p_cdc->ftdi.channel, complete_cb, user_data); } -static bool ftdi_change_speed(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint32_t index_value = ftdi_get_divisor(p_cdc); - TU_VERIFY(index_value); - uint16_t value = (uint16_t) index_value; - uint16_t index = (uint16_t) (index_value >> 16); - if (p_cdc->ftdi.channel) { - index = (uint16_t) ((index << 8) | p_cdc->ftdi.channel); - } - - return ftdi_set_request(p_cdc, FTDI_SIO_SET_BAUDRATE_REQUEST, FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, - value, index, complete_cb, user_data); -} - -static bool ftdi_set_data_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->requested_line.coding.data_bits >= 7 && p_cdc->requested_line.coding.data_bits <= 8, 0); - uint16_t value = (uint16_t) ((p_cdc->requested_line.coding.data_bits & 0xfUL) | // data bit quantity is stored in bits 0-3 - (p_cdc->requested_line.coding.parity & 0x7UL) << 8 | // parity is stored in bits 8-10, same coding - (p_cdc->requested_line.coding.stop_bits & 0x3UL) << 11); // stop bits quantity is stored in bits 11-12, same coding - // not each FTDI supports 1.5 stop bits - - return ftdi_set_request(p_cdc, FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, - value, p_cdc->ftdi.channel, complete_cb, user_data); -} //------------- Driver API -------------// @@ -1199,41 +1190,31 @@ static void ftdi_internal_control_complete(cdch_interface_t* p_cdc, tuh_xfer_t * } static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(ftdi_set_data_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; + TU_VERIFY(p_cdc->requested_line.coding.data_bits >= 7 && p_cdc->requested_line.coding.data_bits <= 8, 0); + uint16_t value = (uint16_t) ((p_cdc->requested_line.coding.data_bits & 0xfUL) | // data bit quantity is stored in bits 0-3 + (p_cdc->requested_line.coding.parity & 0x7UL) << 8 | // parity is stored in bits 8-10, same coding + (p_cdc->requested_line.coding.stop_bits & 0x3UL) << 11); // stop bits quantity is stored in bits 11-12, same coding + // not each FTDI supports 1.5 stop bits + return ftdi_set_request(p_cdc, FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, + value, p_cdc->ftdi.channel, complete_cb, user_data); } static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(ftdi_change_speed(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; -} + uint32_t index_value = ftdi_get_divisor(p_cdc); + TU_VERIFY(index_value); + uint16_t value = (uint16_t) index_value; + uint16_t index = (uint16_t) (index_value >> 16); + if (p_cdc->ftdi.channel) { + index = (uint16_t) ((index << 8) | p_cdc->ftdi.channel); + } -static void ftdi_set_line_coding_stage1_complete(tuh_xfer_t *xfer) { - uint8_t const idx = ftdi_get_idx(xfer); - cdch_interface_t *p_cdc = get_itf(idx); - TU_ASSERT(p_cdc, ); - uint8_t const itf_num = p_cdc->bInterfaceNumber; - set_line_coding_stage1_complete(xfer, itf_num, - ftdi_set_data_request, // control request function to set data format - cdch_internal_control_complete); // control complete function to be called after request -} - -// 2 stages: set baudrate (stage1) + set data format (stage2) -static bool ftdi_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return set_line_coding_sequence(p_cdc, - ftdi_change_speed, // control request function to set baudrate - ftdi_set_data_request, // control request function to set data format - ftdi_set_line_coding_stage1_complete, // function to be called after stage 1 completed - cdch_internal_control_complete, // control complete function to be called after request - complete_cb, user_data); + return ftdi_set_request(p_cdc, FTDI_SIO_SET_BAUDRATE_REQUEST, FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, + value, index, complete_cb, user_data); } static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint16_t line_state = (uint16_t) ((p_cdc->requested_line.control_state.dtr ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW) | (p_cdc->requested_line.control_state.rts ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW)); - p_cdc->user_complete_cb = complete_cb; return ftdi_set_request(p_cdc, FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, line_state, p_cdc->ftdi.channel, complete_cb ? cdch_internal_control_complete : NULL, user_data); } @@ -1243,10 +1224,7 @@ enum { CONFIG_FTDI_DETERMINE_TYPE = 0, CONFIG_FTDI_WRITE_LATENCY, CONFIG_FTDI_SIO_RESET, - CONFIG_FTDI_SET_DATA, - CONFIG_FTDI_SET_BAUDRATE, CONFIG_FTDI_FLOW_CONTROL, - CONFIG_FTDI_MODEM_CTRL, CONFIG_FTDI_COMPLETE }; @@ -1305,48 +1283,20 @@ static bool ftdi_proccess_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) // from here sequence overtaken from Linux Kernel function ftdi_open() case CONFIG_FTDI_SIO_RESET: - p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(ftdi_sio_reset(p_cdc, cdch_process_set_config, CONFIG_FTDI_SET_DATA)); + TU_ASSERT(ftdi_sio_reset(p_cdc, cdch_process_set_config, CONFIG_FTDI_FLOW_CONTROL)); break; - // from here sequence overtaken from Linux Kernel function ftdi_set_termios() - case CONFIG_FTDI_SET_DATA: - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(ftdi_set_data_request(p_cdc, cdch_internal_control_complete, CONFIG_FTDI_SET_BAUDRATE)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - - case CONFIG_FTDI_SET_BAUDRATE: - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(ftdi_change_speed(p_cdc, cdch_internal_control_complete, CONFIG_FTDI_FLOW_CONTROL)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - case CONFIG_FTDI_FLOW_CONTROL: // disable flow control TU_ASSERT(ftdi_set_request(p_cdc, FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, FTDI_SIO_DISABLE_FLOW_CTRL, - p_cdc->ftdi.channel, cdch_process_set_config, CONFIG_FTDI_MODEM_CTRL)); + p_cdc->ftdi.channel, cdch_process_set_config, CONFIG_FTDI_COMPLETE)); break; - case CONFIG_FTDI_MODEM_CTRL: - #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT(ftdi_set_modem_ctrl(p_cdc, cdch_process_set_config, CONFIG_FTDI_COMPLETE)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - - case CONFIG_FTDI_COMPLETE: - set_config_complete(p_cdc, 0, true); + case CONFIG_FTDI_COMPLETE: { + xfer->user_data = 0; // kick-off set line state on enum + cdch_process_line_state_on_enum(xfer); break; + } default: return false; @@ -1562,20 +1512,6 @@ static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { return div_value; } -static uint8_t ftdi_get_idx(tuh_xfer_t *xfer) { - uint8_t const channel = (uint8_t) tu_le16toh(xfer->setup->wIndex);// channel index, or 0 for legacy types - for (uint8_t i = 0; i < CFG_TUH_CDC; i++) { - const cdch_interface_t *p_cdc = &cdch_data[i]; - if (p_cdc->daddr == xfer->daddr && - (!p_cdc->ftdi.channel || // 0 for legacy types (only interface 0) - channel == p_cdc->ftdi.channel)) {// or multi-channel types (interfaces 0..n) - return i; - } - } - - return TUSB_INDEX_INVALID_8; -} - #endif //--------------------------------------------------------------------+ @@ -1619,32 +1555,14 @@ static bool cp210x_set_request(cdch_interface_t * p_cdc, uint8_t command, uint16 return tuh_control_xfer(&xfer); } -static inline bool cp210x_ifc_enable(cdch_interface_t *p_cdc, uint16_t enabled, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE static inline bool cp210x_ifc_enable(cdch_interface_t *p_cdc, uint16_t enabled, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return cp210x_set_request(p_cdc, CP210X_IFC_ENABLE, enabled, NULL, 0, complete_cb, user_data); } -static bool cp210x_set_baudrate_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - // Not every baud rate is supported. See datasheets and AN205 "CP210x Baud Rate Support" - uint32_t baud_le = tu_htole32(p_cdc->requested_line.coding.bit_rate); - - return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, complete_cb, user_data); -} - -static bool cp210x_set_line_ctl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->requested_line.coding.data_bits >= 5 && p_cdc->requested_line.coding.data_bits <= 8, 0); - uint16_t lcr = (uint16_t) ((p_cdc->requested_line.coding.data_bits & 0xfUL) << 8 | // data bit quantity is stored in bits 8-11 - (p_cdc->requested_line.coding.parity & 0xfUL) << 4 | // parity is stored in bits 4-7, same coding - (p_cdc->requested_line.coding.stop_bits & 0xfUL)); // parity is stored in bits 0-3, same coding - - return cp210x_set_request(p_cdc, CP210X_SET_LINE_CTL, lcr, NULL, 0, complete_cb, user_data); -} - -static inline bool cp210x_set_mhs(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE static inline bool cp210x_set_mhs(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // CP210x has the same bit coding return cp210x_set_request(p_cdc, CP210X_SET_MHS, - (uint16_t) (CP210X_CONTROL_WRITE_DTR | CP210X_CONTROL_WRITE_RTS | - p_cdc->requested_line.control_state.value), + (uint16_t) (CP210X_CONTROL_WRITE_DTR | CP210X_CONTROL_WRITE_RTS | p_cdc->requested_line.control_state.value), NULL, 0, complete_cb, user_data); } @@ -1673,47 +1591,28 @@ static void cp210x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t } static bool cp210x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(cp210x_set_baudrate_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; + // Not every baud rate is supported. See datasheets and AN205 "CP210x Baud Rate Support" + uint32_t baud_le = tu_htole32(p_cdc->requested_line.coding.bit_rate); + return cp210x_set_request(p_cdc, CP210X_SET_BAUDRATE, 0, (uint8_t *) &baud_le, 4, complete_cb, user_data); } static bool cp210x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(cp210x_set_line_ctl(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; -} + TU_VERIFY(p_cdc->requested_line.coding.data_bits >= 5 && p_cdc->requested_line.coding.data_bits <= 8, 0); + uint16_t lcr = (uint16_t) ((p_cdc->requested_line.coding.data_bits & 0xfUL) << 8 | // data bit quantity is stored in bits 8-11 + (p_cdc->requested_line.coding.parity & 0xfUL) << 4 | // parity is stored in bits 4-7, same coding + (p_cdc->requested_line.coding.stop_bits & 0xfUL)); // parity is stored in bits 0-3, same coding -static void cp210x_set_line_coding_stage1_complete(tuh_xfer_t *xfer) { - uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - set_line_coding_stage1_complete(xfer, itf_num, - cp210x_set_line_ctl, // control request function to set data format - cdch_internal_control_complete); // control complete function to be called after request -} - -// 2 stages: set baudrate (stage1) + set data format (stage2) -static bool cp210x_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return set_line_coding_sequence(p_cdc, - cp210x_set_baudrate_request, // control request function to set baudrate - cp210x_set_line_ctl, // control request function to set data format - cp210x_set_line_coding_stage1_complete, // function to be called after stage 1 completed - cdch_internal_control_complete, // control complete function to be called after request - complete_cb, user_data); + return cp210x_set_request(p_cdc, CP210X_SET_LINE_CTL, lcr, NULL, 0, complete_cb, user_data); } static bool cp210x_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(cp210x_set_mhs(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; + return cp210x_set_mhs(p_cdc, complete_cb, user_data); } //------------- Enumeration -------------// enum { CONFIG_CP210X_IFC_ENABLE = 0, - CONFIG_CP210X_SET_BAUDRATE_REQUEST, - CONFIG_CP210X_SET_LINE_CTL, - CONFIG_CP210X_SET_DTR_RTS, CONFIG_CP210X_COMPLETE }; @@ -1740,40 +1639,12 @@ static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) switch (state) { case CONFIG_CP210X_IFC_ENABLE: - TU_ASSERT(cp210x_ifc_enable(p_cdc, CP210X_UART_ENABLE, cdch_process_set_config, CONFIG_CP210X_SET_BAUDRATE_REQUEST)); + TU_ASSERT(cp210x_ifc_enable(p_cdc, CP210X_UART_ENABLE, cdch_process_set_config, CONFIG_CP210X_COMPLETE)); break; - case CONFIG_CP210X_SET_BAUDRATE_REQUEST: - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(cp210x_set_baudrate_request(p_cdc, cdch_internal_control_complete, CONFIG_CP210X_SET_LINE_CTL)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - - case CONFIG_CP210X_SET_LINE_CTL: - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(cp210x_set_line_ctl(p_cdc, cdch_internal_control_complete, CONFIG_CP210X_SET_DTR_RTS)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - - case CONFIG_CP210X_SET_DTR_RTS: - #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(cp210x_set_mhs(p_cdc, cdch_internal_control_complete, CONFIG_CP210X_COMPLETE)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - case CONFIG_CP210X_COMPLETE: - set_config_complete(p_cdc, 0, true); + xfer->user_data = 0;// kick-off set line state on enum + cdch_process_line_state_on_enum(xfer); break; default: @@ -1833,19 +1704,19 @@ static bool ch34x_set_request(cdch_interface_t *p_cdc, uint8_t direction, uint8_ return tuh_control_xfer(&xfer); } -static inline bool ch34x_control_out(cdch_interface_t *p_cdc, uint8_t request, uint16_t value, uint16_t index, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE static inline bool ch34x_control_out(cdch_interface_t *p_cdc, uint8_t request, uint16_t value, uint16_t index, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ch34x_set_request(p_cdc, TUSB_DIR_OUT, request, value, index, NULL, 0, complete_cb, user_data); } -static inline bool ch34x_control_in(cdch_interface_t *p_cdc, uint8_t request, uint16_t value, uint16_t index, - uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE static inline bool ch34x_control_in(cdch_interface_t *p_cdc, uint8_t request, uint16_t value, uint16_t index, + uint8_t *buffer, uint16_t buffersize, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ch34x_set_request(p_cdc, TUSB_DIR_IN, request, value, index, buffer, buffersize, complete_cb, user_data); } -static inline bool ch34x_write_reg(cdch_interface_t *p_cdc, uint16_t reg, uint16_t reg_value, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE static inline bool ch34x_write_reg(cdch_interface_t *p_cdc, uint16_t reg, uint16_t reg_value, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return ch34x_control_out(p_cdc, CH34X_REQ_WRITE_REG, reg, reg_value, complete_cb, user_data); } @@ -1855,25 +1726,6 @@ static inline bool ch34x_write_reg(cdch_interface_t *p_cdc, uint16_t reg, uint16 // return ch34x_control_in ( p_cdc, CH34X_REQ_READ_REG, reg, 0, buffer, buffersize, complete_cb, user_data ); //} -static bool ch34x_write_reg_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint8_t const lcr = ch34x_get_lcr(p_cdc); - TU_VERIFY(lcr); - return ch34x_write_reg(p_cdc, CH32X_REG16_LCR2_LCR, lcr, complete_cb, user_data); -} - -static bool ch34x_write_reg_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - uint16_t const div_ps = ch34x_get_divisor_prescaler(p_cdc); - TU_VERIFY(div_ps); - return ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, complete_cb, user_data); -} - -static bool ch34x_modem_ctrl_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - // CH34x signals are inverted - uint8_t control = ~((p_cdc->requested_line.control_state.rts ? CH34X_BIT_RTS : 0) | - (p_cdc->requested_line.control_state.dtr ? CH34X_BIT_DTR : 0)); - return ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, complete_cb, user_data); -} - //------------- Driver API -------------// // internal control complete to update state such as line state, encoding @@ -1908,39 +1760,22 @@ static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t } static bool ch34x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(ch34x_write_reg_data_format(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; + const uint8_t lcr = ch34x_get_lcr(p_cdc); + TU_VERIFY(lcr); + return ch34x_write_reg(p_cdc, CH32X_REG16_LCR2_LCR, lcr, complete_cb, user_data); } static bool ch34x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(ch34x_write_reg_baudrate(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; -} - -static void ch34x_set_line_coding_stage1_complete(tuh_xfer_t *xfer) { - // CH34x has only interface 0, because wIndex is used as payload and not for bInterfaceNumber - uint8_t const itf_num = 0; - set_line_coding_stage1_complete(xfer, itf_num, - ch34x_write_reg_data_format, // control request function to set data format - cdch_internal_control_complete); // control complete function to be called after request -} - -// 2 stages: set baudrate (stage1) + set data format (stage2) -static bool ch34x_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return set_line_coding_sequence(p_cdc, - ch34x_write_reg_baudrate, // control request function to set baudrate - ch34x_write_reg_data_format, // control request function to set data format - ch34x_set_line_coding_stage1_complete, // function to be called after stage 1 completed - cdch_internal_control_complete, // control complete function to be called after request - complete_cb, user_data); + const uint16_t div_ps = ch34x_get_divisor_prescaler(p_cdc); + TU_VERIFY(div_ps); + return ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, complete_cb, user_data); } static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; + // CH34x signals are inverted + uint8_t control = ~((p_cdc->requested_line.control_state.rts ? CH34X_BIT_RTS : 0) | + (p_cdc->requested_line.control_state.dtr ? CH34X_BIT_DTR : 0)); + return ch34x_control_out(p_cdc, CH34X_REQ_MODEM_CTRL, control, 0, complete_cb, user_data); } //------------- Enumeration -------------// @@ -1950,7 +1785,6 @@ enum { CONFIG_CH34X_SERIAL_INIT, CONFIG_CH34X_SPECIAL_REG_WRITE, CONFIG_CH34X_FLOW_CONTROL, - CONFIG_CH34X_MODEM_CONTROL, CONFIG_CH34X_COMPLETE }; @@ -2018,25 +1852,16 @@ static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_CH34X_FLOW_CONTROL: // no hardware flow control TU_ASSERT(ch34x_write_reg(p_cdc, TU_U16(CH341_REG_0x27, CH341_REG_0x27), 0x0000, - cdch_process_set_config, CONFIG_CH34X_MODEM_CONTROL)); + cdch_process_set_config, CONFIG_CH34X_COMPLETE)); break; - case CONFIG_CH34X_MODEM_CONTROL: - #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - p_cdc->user_complete_cb = cdch_process_set_config; - TU_ASSERT(ch34x_modem_ctrl_request(p_cdc, cdch_internal_control_complete, CONFIG_CH34X_COMPLETE)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - case CONFIG_CH34X_COMPLETE: - set_config_complete(p_cdc, 0, true); + xfer->user_data = 0; // kick-off set line state on enum + cdch_process_line_state_on_enum(xfer); break; default: - break; + return false; } return true; diff --git a/src/class/cdc/serial/ch34x.h b/src/class/cdc/serial/ch34x.h index 7d91f01fe..0e08b0acd 100644 --- a/src/class/cdc/serial/ch34x.h +++ b/src/class/cdc/serial/ch34x.h @@ -34,9 +34,9 @@ // set line_coding @ enumeration #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM -#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X CFG_TUH_CDC_LINE_CODING_ON_ENUM + #define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X CFG_TUH_CDC_LINE_CODING_ON_ENUM #else // this default is necessary to work properly -#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X { 9600, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } + #define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X { 9600, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 } #endif // USB requests From f4d049e61ba12c8ba6fcd23c18fe5089ff899186 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Jun 2025 17:05:49 +0700 Subject: [PATCH 243/382] update acm and pl2303 to match the rest of drivers --- src/class/cdc/cdc_host.c | 218 +++++++++++---------------------------- 1 file changed, 59 insertions(+), 159 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 7926aa9fc..81337cde4 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -117,8 +117,6 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); static void acm_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static bool acm_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool acm_set_control_line_state(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -169,8 +167,6 @@ static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, u static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); static void pl2303_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static bool pl2303_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool pl2303_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool pl2303_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); static bool pl2303_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); #endif @@ -228,10 +224,9 @@ static const cdch_serial_driver_t serial_drivers[] = { .open = acm_open, .process_set_config = acm_process_set_config, .request_complete = acm_internal_control_complete, - .set_control_line_state = acm_set_control_line_state, - .set_baudrate = acm_set_baudrate, - .set_data_format = acm_set_data_format, + .set_baudrate = acm_set_line_coding, + .set_data_format = acm_set_line_coding, .set_line_coding = acm_set_line_coding, DRIVER_NAME_DECLARE("ACM") }, @@ -290,8 +285,8 @@ static const cdch_serial_driver_t serial_drivers[] = { .process_set_config = pl2303_process_set_config, .request_complete = pl2303_internal_control_complete, .set_control_line_state = pl2303_set_modem_ctrl, - .set_baudrate = pl2303_set_baudrate, - .set_data_format = pl2303_set_data_format, + .set_baudrate = pl2303_set_line_coding, + .set_data_format = pl2303_set_line_coding, .set_line_coding = pl2303_set_line_coding, DRIVER_NAME_DECLARE("PL2303") } @@ -586,10 +581,11 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, CDC_LINE_CODING_STOP_BITS_TEXT(line_coding->stop_bits)); cdch_serial_driver_t const *driver = &serial_drivers[p_cdc->serial_drid]; p_cdc->requested_line.coding = *line_coding; + p_cdc->user_complete_cb = complete_cb; if (driver->set_line_coding) { // driver support set_line_coding request - TU_VERIFY(driver->set_line_coding(p_cdc, complete_cb, user_data)); + TU_VERIFY(driver->set_line_coding(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); if (!complete_cb) { p_cdc->line.coding = *line_coding; @@ -598,7 +594,6 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, // driver does not support set_line_coding and need 2 stage to set baudrate and data format separately if (complete_cb) { // non-blocking - p_cdc->user_complete_cb = complete_cb; TU_VERIFY(driver->set_baudrate(p_cdc, cdch_set_line_coding_stage1_baudrate_complete, user_data)); } else { // blocking @@ -795,7 +790,7 @@ bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { return true; } -static void set_config_complete(cdch_interface_t *p_cdc, uint8_t itf_offset, bool success) { +static void set_config_complete(cdch_interface_t *p_cdc, bool success) { if (success) { const uint8_t idx = get_idx_by_ptr(p_cdc); p_cdc->mounted = true; @@ -811,6 +806,7 @@ static void set_config_complete(cdch_interface_t *p_cdc, uint8_t itf_offset, boo } // notify usbh that driver enumeration is complete + const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; usbh_driver_set_config_complete(p_cdc->daddr, p_cdc->bInterfaceNumber + itf_offset); } @@ -821,8 +817,7 @@ static void cdch_process_set_config(tuh_xfer_t *xfer) { const cdch_serial_driver_t *driver = &serial_drivers[p_cdc->serial_drid]; if (!driver->process_set_config(p_cdc, xfer)) { - const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; - set_config_complete(p_cdc, itf_offset, false); + set_config_complete(p_cdc, false); } } @@ -858,11 +853,9 @@ static bool set_line_state_on_enum(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { TU_ATTR_FALLTHROUGH; #endif - case ENUM_SET_LINE_COMPLETE: { - const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; - set_config_complete(p_cdc, itf_offset, true); + case ENUM_SET_LINE_COMPLETE: + set_config_complete(p_cdc, true); break; - } default: return false; @@ -874,11 +867,8 @@ static bool set_line_state_on_enum(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { static void cdch_process_line_state_on_enum(tuh_xfer_t *xfer) { cdch_interface_t *p_cdc = get_itf_by_xfer(xfer); TU_ASSERT(p_cdc && p_cdc->serial_drid < SERIAL_DRIVER_COUNT,); - TU_LOG_DRV(" xfer result = %u\r\n", xfer->result); - if (xfer->result != XFER_RESULT_SUCCESS || !set_line_state_on_enum(p_cdc, xfer)) { - const uint8_t itf_offset = (p_cdc->serial_drid == SERIAL_DRIVER_ACM) ? 1 : 0; - set_config_complete(p_cdc, itf_offset, false); + set_config_complete(p_cdc, false); } } @@ -967,20 +957,16 @@ static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t co .wLength = 0 }; - p_cdc->user_complete_cb = complete_cb; - tuh_xfer_t xfer = { .daddr = p_cdc->daddr, .ep_addr = 0, .setup = &request, .buffer = NULL, - .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, + .complete_cb = complete_cb, .user_data = user_data }; - TU_ASSERT(tuh_control_xfer(&xfer)); - - return true; + return tuh_control_xfer(&xfer); } static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { @@ -1004,35 +990,21 @@ static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_ uint8_t *enum_buf = usbh_get_enum_buf(); memcpy(enum_buf, &p_cdc->requested_line.coding, sizeof(cdc_line_coding_t)); - p_cdc->user_complete_cb = complete_cb; - tuh_xfer_t xfer = { .daddr = p_cdc->daddr, .ep_addr = 0, .setup = &request, .buffer = enum_buf, - .complete_cb = complete_cb ? cdch_internal_control_complete : NULL, + .complete_cb = complete_cb, .user_data = user_data }; - TU_ASSERT(tuh_control_xfer(&xfer)); - - return true; -} - -static bool acm_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return acm_set_line_coding(p_cdc, complete_cb, user_data); -} - -static bool acm_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return acm_set_line_coding(p_cdc, complete_cb, user_data); + return tuh_control_xfer(&xfer); } //------------- Enumeration -------------// enum { - CONFIG_ACM_SET_CONTROL_LINE_STATE = 0, - CONFIG_ACM_SET_LINE_CODING, - CONFIG_ACM_COMPLETE + CONFIG_ACM_COMPLETE = 0 }; static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { @@ -1084,30 +1056,11 @@ static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); const uintptr_t state = xfer->user_data; switch (state) { - case CONFIG_ACM_SET_CONTROL_LINE_STATE: - #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - if (p_cdc->acm.capability.support_line_request) { - p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT(acm_set_control_line_state(p_cdc, cdch_process_set_config, CONFIG_ACM_SET_LINE_CODING)); - break; - } - #endif - TU_ATTR_FALLTHROUGH; - - case CONFIG_ACM_SET_LINE_CODING: - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - if (p_cdc->acm.capability.support_line_request) { - p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(acm_set_line_coding(p_cdc, cdch_process_set_config, CONFIG_ACM_COMPLETE)); - break; - } - #endif - TU_ATTR_FALLTHROUGH; - - case CONFIG_ACM_COMPLETE: - // itf_num+1 to account for data interface as well - set_config_complete(p_cdc, 1, true); + case CONFIG_ACM_COMPLETE: { + xfer->user_data = 0; // kick-off set line state on enum + cdch_process_line_state_on_enum(xfer); break; + } default: return false; // invalid state @@ -2023,18 +1976,40 @@ static inline bool pl2303_supports_hx_status(cdch_interface_t *p_cdc, tuh_xfer_c &buf, 1, complete_cb, user_data); } -static inline bool pl2303_set_control_lines(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - // PL2303 has the same bit coding - return pl2303_set_request(p_cdc, PL2303_SET_CONTROL_REQUEST, PL2303_SET_CONTROL_REQUEST_TYPE, - p_cdc->requested_line.control_state.value, 0, NULL, 0, complete_cb, user_data); -} - -//static bool pl2303_get_line_request(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BUFSIZE]) -//{ +//static bool pl2303_get_line_request(cdch_interface_t * p_cdc, uint8_t buf[PL2303_LINE_CODING_BUFSIZE]) { // return pl2303_set_request(p_cdc, PL2303_GET_LINE_REQUEST, PL2303_GET_LINE_REQUEST_TYPE, 0, 0, buf, PL2303_LINE_CODING_BUFSIZE); //} -static bool pl2303_set_line_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +//static bool pl2303_set_break(cdch_interface_t * p_cdc, bool enable) { +// uint16_t state = enable ? PL2303_BREAK_ON : PL2303_BREAK_OFF; +// return pl2303_set_request(p_cdc, PL2303_BREAK_REQUEST, PL2303_BREAK_REQUEST_TYPE, state, 0, NULL, 0); +//} + +static inline int pl2303_clear_halt(cdch_interface_t *p_cdc, uint8_t endp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + /* we don't care if it wasn't halted first. in fact some devices + * (like some ibmcam model 1 units) seem to expect hosts to make + * this request for iso endpoints, which can't halt! + */ + return pl2303_set_request(p_cdc, TUSB_REQ_CLEAR_FEATURE, PL2303_CLEAR_HALT_REQUEST_TYPE, TUSB_REQ_FEATURE_EDPT_HALT, endp, + NULL, 0, complete_cb, user_data); +} + +//------------- Driver API -------------// + +// internal control complete to update state such as line state, encoding +static void pl2303_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { + TU_VERIFY(xfer->result == XFER_RESULT_SUCCESS,); + if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && + xfer->setup->bmRequestType == PL2303_SET_LINE_REQUEST_TYPE) { + p_cdc->line.coding = p_cdc->requested_line.coding; + } + if (xfer->setup->bRequest == PL2303_SET_CONTROL_REQUEST && + xfer->setup->bmRequestType == PL2303_SET_CONTROL_REQUEST_TYPE) { + p_cdc->line.control_state = p_cdc->requested_line.control_state; + } +} + +static bool pl2303_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // the caller has to precheck, that the new line coding different than the current, else false returned uint8_t buf[PL2303_LINE_CODING_BUFSIZE]; /* @@ -2070,63 +2045,10 @@ static bool pl2303_set_line_request(cdch_interface_t *p_cdc, tuh_xfer_cb_t compl buf, PL2303_LINE_CODING_BUFSIZE, complete_cb, user_data); } -//static bool pl2303_set_break(cdch_interface_t * p_cdc, bool enable) -//{ -// uint16_t state = enable ? PL2303_BREAK_ON : PL2303_BREAK_OFF; -// return pl2303_set_request(p_cdc, PL2303_BREAK_REQUEST, PL2303_BREAK_REQUEST_TYPE, state, 0, NULL, 0); -//} - -static inline int pl2303_clear_halt(cdch_interface_t *p_cdc, uint8_t endp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - /* we don't care if it wasn't halted first. in fact some devices - * (like some ibmcam model 1 units) seem to expect hosts to make - * this request for iso endpoints, which can't halt! - */ - return pl2303_set_request(p_cdc, TUSB_REQ_CLEAR_FEATURE, PL2303_CLEAR_HALT_REQUEST_TYPE, TUSB_REQ_FEATURE_EDPT_HALT, endp, - NULL, 0, complete_cb, user_data); -} - -//------------- Driver API -------------// - -// internal control complete to update state such as line state, encoding -static void pl2303_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { - TU_VERIFY(xfer->result == XFER_RESULT_SUCCESS,); - if (xfer->setup->bRequest == PL2303_SET_LINE_REQUEST && - xfer->setup->bmRequestType == PL2303_SET_LINE_REQUEST_TYPE) { - p_cdc->line.coding = p_cdc->requested_line.coding; - } - if (xfer->setup->bRequest == PL2303_SET_CONTROL_REQUEST && - xfer->setup->bmRequestType == PL2303_SET_CONTROL_REQUEST_TYPE) { - p_cdc->line.control_state = p_cdc->requested_line.control_state; - } -} - -static bool pl2303_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; -} - -static bool pl2303_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->requested_line.coding.bit_rate = p_cdc->line.coding.bit_rate; - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; -} - -static bool pl2303_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - p_cdc->requested_line.coding.stop_bits = p_cdc->line.coding.stop_bits; - p_cdc->requested_line.coding.parity = p_cdc->line.coding.parity; - p_cdc->requested_line.coding.data_bits = p_cdc->line.coding.data_bits; - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(pl2303_set_line_request(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; -} - static bool pl2303_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { // PL2303 has the same bit coding - p_cdc->user_complete_cb = complete_cb; - TU_ASSERT(pl2303_set_control_lines(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); - return true; + return pl2303_set_request(p_cdc, PL2303_SET_CONTROL_REQUEST, PL2303_SET_CONTROL_REQUEST_TYPE, + p_cdc->requested_line.control_state.value, 0, NULL, 0, complete_cb, user_data); } //------------- Enumeration -------------// @@ -2146,8 +2068,6 @@ enum { CONFIG_PL2303_WRITE5, CONFIG_PL2303_RESET_ENDP1, CONFIG_PL2303_RESET_ENDP2, - CONFIG_PL2303_LINE_CODING, - CONFIG_PL2303_MODEM_CONTROL, // CONFIG_PL2303_FLOW_CTRL_READ, // CONFIG_PL2303_FLOW_CTRL_WRITE, CONFIG_PL2303_COMPLETE @@ -2190,7 +2110,6 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) switch (state) { // from here sequence overtaken from Linux Kernel function pl2303_startup() case CONFIG_PL2303_DETECT_TYPE: - p_cdc->user_complete_cb = cdch_process_set_config;// set once for whole process config // get type and quirks (step 1) type = pl2303_detect_type(p_cdc, 1); TU_ASSERT(type != PL2303_TYPE_UNKNOWN); @@ -2313,7 +2232,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) if (p_cdc->pl2303.type == PL2303_TYPE_HXN) { TU_ASSERT(pl2303_vendor_write(p_cdc, PL2303_HXN_RESET_REG,// skip CONFIG_PL2303_RESET_ENDP2, no 2nd step PL2303_HXN_RESET_UPSTREAM_PIPE | PL2303_HXN_RESET_DOWNSTREAM_PIPE, - cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); + cdch_process_set_config, CONFIG_PL2303_COMPLETE)); } else { pl2303_vendor_write(p_cdc, 8, 0, cdch_process_set_config, CONFIG_PL2303_RESET_ENDP2); } @@ -2323,37 +2242,17 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_RESET_ENDP2: // step 2 if (p_cdc->pl2303.quirks & PL2303_QUIRK_LEGACY) { - TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_IN_EP, cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); + TU_ASSERT(pl2303_clear_halt(p_cdc, PL2303_IN_EP, cdch_process_set_config, CONFIG_PL2303_COMPLETE)); } else { /* reset upstream data pipes */ if (p_cdc->pl2303.type == PL2303_TYPE_HXN) { // here nothing to do, only structure of previous step overtaken for better reading and comparison } else { - TU_ASSERT(pl2303_vendor_write(p_cdc, 9, 0, cdch_process_set_config, CONFIG_PL2303_LINE_CODING)); + TU_ASSERT(pl2303_vendor_write(p_cdc, 9, 0, cdch_process_set_config, CONFIG_PL2303_COMPLETE)); } } break; - // from here sequence overtaken from Linux Kernel function pl2303_set_termios() - // unnecessary pl2303_get_line_request() is skipped due to a stall - case CONFIG_PL2303_LINE_CODING: - #ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM - p_cdc->requested_line.coding = (cdc_line_coding_t) CFG_TUH_CDC_LINE_CODING_ON_ENUM; - TU_ASSERT(pl2303_set_line_request(p_cdc, cdch_internal_control_complete, CONFIG_PL2303_MODEM_CONTROL)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - - case CONFIG_PL2303_MODEM_CONTROL: - #ifdef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM - p_cdc->requested_line.control_state.value = CFG_TUH_CDC_LINE_CONTROL_ON_ENUM; - TU_ASSERT(pl2303_set_control_lines(p_cdc, cdch_internal_control_complete, CONFIG_PL2303_COMPLETE)); - break; - #else - TU_ATTR_FALLTHROUGH; - #endif - // skipped, because it's not working with each PL230x. flow control can be also set by PL2303 EEPROM Writer Program // case CONFIG_PL2303_FLOW_CTRL_READ: // // read flow control register for modify & write back in next step @@ -2383,7 +2282,8 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) // break; case CONFIG_PL2303_COMPLETE: - set_config_complete(p_cdc, 0, true); + xfer->user_data = 0; // kick-off set line state on enum + cdch_process_line_state_on_enum(xfer); break; default: From 0194b8434f318b2bd7357ba954291d03d3b26286 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Jun 2025 17:25:20 +0700 Subject: [PATCH 244/382] use enum buf for process_set_config for ch34x and pl2303 --- src/class/cdc/cdc_host.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 81337cde4..ebbd9c18c 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -1054,7 +1054,9 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint1 static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); + (void) p_cdc; const uintptr_t state = xfer->user_data; + switch (state) { case CONFIG_ACM_COMPLETE: { xfer->user_data = 0; // kick-off set line state on enum @@ -1767,15 +1769,16 @@ static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, ui } static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { - uint8_t buffer[2];// TODO remove TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS); const uintptr_t state = xfer->user_data; switch (state) { - case CONFIG_CH34X_READ_VERSION: - TU_ASSERT(ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, buffer, 2, + case CONFIG_CH34X_READ_VERSION: { + uint8_t* enum_buf = usbh_get_enum_buf(); + TU_ASSERT(ch34x_control_in(p_cdc, CH34X_REQ_READ_VERSION, 0, 0, enum_buf, 2, cdch_process_set_config, CONFIG_CH34X_SERIAL_INIT)); break; + } case CONFIG_CH34X_SERIAL_INIT: { // handle version read data, set CH34x line coding (incl. baudrate) @@ -2104,7 +2107,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) // state CONFIG_PL2303_READ1 may have no success due to expected stall by pl2303_supports_hx_status() const uintptr_t state = xfer->user_data; TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS || state == CONFIG_PL2303_READ1); - uint8_t buf = 0; + uint8_t* enum_buf = usbh_get_enum_buf(); pl2303_type_t type; switch (state) { @@ -2136,7 +2139,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE1)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, enum_buf, cdch_process_set_config, CONFIG_PL2303_WRITE1)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2152,7 +2155,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_READ2: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_READ3)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, enum_buf, cdch_process_set_config, CONFIG_PL2303_READ3)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2160,7 +2163,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_READ3: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, cdch_process_set_config, CONFIG_PL2303_READ4)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, enum_buf, cdch_process_set_config, CONFIG_PL2303_READ4)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2168,7 +2171,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_READ4: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE2)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, enum_buf, cdch_process_set_config, CONFIG_PL2303_WRITE2)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2184,7 +2187,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_READ5: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, &buf, cdch_process_set_config, CONFIG_PL2303_READ6)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8484, enum_buf, cdch_process_set_config, CONFIG_PL2303_READ6)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; @@ -2192,7 +2195,7 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) case CONFIG_PL2303_READ6: // purpose unknown, overtaken from Linux Kernel driver if (p_cdc->pl2303.type != PL2303_TYPE_HXN) { - TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, &buf, cdch_process_set_config, CONFIG_PL2303_WRITE3)); + TU_ASSERT(pl2303_vendor_read(p_cdc, 0x8383, enum_buf, cdch_process_set_config, CONFIG_PL2303_WRITE3)); break; }// else: continue with next step TU_ATTR_FALLTHROUGH; From d86362414e9c467d93f37672228e220a718de81d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Jun 2025 17:57:26 +0700 Subject: [PATCH 245/382] clean up --- examples/host/cdc_msc_hid/src/tusb_config.h | 3 +- .../cdc_msc_hid_freertos/src/tusb_config.h | 1 + src/class/cdc/cdc_host.c | 32 +++++++++---------- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index e610c5672..2f8cb5e03 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -103,7 +103,7 @@ #define CFG_TUH_ENUMERATION_BUFSIZE 256 #define CFG_TUH_HUB 1 // number of supported hubs -#define CFG_TUH_CDC 4 // number of supported CDC devices. also activates CDC ACM +#define CFG_TUH_CDC 2 // number of supported CDC devices. also activates CDC ACM #define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API #define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API @@ -122,6 +122,7 @@ //------------- CDC -------------// // Set Line Control state on enumeration/mounted: +// DTR ( bit 0), RTS (bit 1) #define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM (CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS) // Set Line Coding on enumeration/mounted, value for cdc_line_coding_t diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index 05deecba0..bc8887211 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -127,6 +127,7 @@ //------------- CDC -------------// // Set Line Control state on enumeration/mounted: +// DTR ( bit 0), RTS (bit 1) #define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM (CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS) // Set Line Coding on enumeration/mounted, value for cdc_line_coding_t diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index ebbd9c18c..f4567fac4 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -42,7 +42,7 @@ // Level where CFG_TUSB_DEBUG must be at least for this driver is logged #ifndef CFG_TUH_CDC_LOG_LEVEL - #define CFG_TUH_CDC_LOG_LEVEL 1 + #define CFG_TUH_CDC_LOG_LEVEL 2 #endif #define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) @@ -748,25 +748,25 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d (void) rhport; // For CDC: only support ACM subclass // Note: Protocol 0xFF can be RNDIS device - if (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + if (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass) { return acm_open(daddr, itf_desc, max_len); - } else if (SERIAL_DRIVER_COUNT > 1 && - TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { - uint16_t vid, pid; - TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); + } else if (SERIAL_DRIVER_COUNT > 1 && + TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { + uint16_t vid, pid; + TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); - for (size_t dr = 1; dr < SERIAL_DRIVER_COUNT; dr++) { - const cdch_serial_driver_t *driver = &serial_drivers[dr]; - for (size_t i = 0; i < driver->vid_pid_count; i++) { - if (driver->vid_pid_list[i][0] == vid && driver->vid_pid_list[i][1] == pid) { - const bool ret = driver->open(daddr, itf_desc, max_len); - TU_LOG_DRV("[:%u:%u] CDCh %s open %s\r\n", daddr, itf_desc->bInterfaceNumber, driver->name, ret ? "OK" : "FAILED"); - return ret; - } - } + for (size_t dr = 1; dr < SERIAL_DRIVER_COUNT; dr++) { + const cdch_serial_driver_t *driver = &serial_drivers[dr]; + for (size_t i = 0; i < driver->vid_pid_count; i++) { + if (driver->vid_pid_list[i][0] == vid && driver->vid_pid_list[i][1] == pid) { + const bool ret = driver->open(daddr, itf_desc, max_len); + TU_LOG_DRV("[:%u:%u] CDCh %s open %s\r\n", daddr, itf_desc->bInterfaceNumber, driver->name, ret ? "OK" : "FAILED"); + return ret; } - } + } + } + } return false; } From d22cbe4cb5b88c869754e91c97eff513ed8b7b33 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 1 Jul 2025 20:13:21 +0700 Subject: [PATCH 246/382] refactor async io, add in_isr argument to tud_msc_async_io_done() use cbw.command[0] for pending IO command --- src/class/msc/msc_device.c | 211 +++++++++++++++++-------------------- src/class/msc/msc_device.h | 70 +++++------- 2 files changed, 123 insertions(+), 158 deletions(-) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index e583f6ba8..709734b87 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -52,36 +52,27 @@ enum { MSC_STAGE_NEED_RESET, }; -enum { - MSC_NEXT_OP_NONE = 0, - MSC_NEXT_OP_READ10, - MSC_NEXT_OP_WRITE10, - MSC_NEXT_OP_STATUS -}; - typedef struct { - TU_ATTR_ALIGNED(4) msc_cbw_t cbw; - TU_ATTR_ALIGNED(4) msc_csw_t csw; - + TU_ATTR_ALIGNED(4) msc_cbw_t cbw; // 31 bytes uint8_t rhport; + + TU_ATTR_ALIGNED(4) msc_csw_t csw; // 13 bytes uint8_t itf_num; uint8_t ep_in; uint8_t ep_out; - // Bulk Only Transfer (BOT) Protocol - uint8_t stage; - uint32_t total_len; // byte to be transferred, can be smaller than total_bytes in cbw uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage - // Sense Response Data + // Bulk Only Transfer (BOT) Protocol + uint8_t stage; + + // SCSI Sense Response Data uint8_t sense_key; uint8_t add_sense_code; uint8_t add_sense_qualifier; - // Async IO - uint8_t next_op; - uint32_t xferred_bytes; + uint8_t pending_io; // pending async IO }mscd_interface_t; static mscd_interface_t _mscd_itf; @@ -95,12 +86,11 @@ CFG_TUD_MEM_SECTION static struct { //--------------------------------------------------------------------+ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize); static void proc_read10_cmd(mscd_interface_t* p_msc); -static void proc_read10_next(mscd_interface_t* p_msc, int32_t nbytes); +static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes); static void proc_write10_cmd(mscd_interface_t* p_msc); -static void proc_write10_new_data(mscd_interface_t* p_msc, uint32_t xferred_bytes); -static void proc_write10_next(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes); +static void proc_write10_host_data(mscd_interface_t* p_msc, uint32_t xferred_bytes); +static void proc_write_io_data(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes); static bool proc_stage_status(mscd_interface_t* p_msc); -static void tud_msc_async_io_done_cb(void* bytes_processed); TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) { return tu_bit_test(dir, 7); @@ -195,30 +185,31 @@ static uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) { return status; } -static bool proc_stage_status(mscd_interface_t* p_msc) { +static bool proc_stage_status(mscd_interface_t *p_msc) { uint8_t rhport = p_msc->rhport; - msc_cbw_t const* p_cbw = &p_msc->cbw; - // skip status if epin is currently stalled, will do it when received Clear Stall request - if (!usbd_edpt_stalled(rhport, p_msc->ep_in)) { - if ((p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir)) { - // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status - // TU_LOG_DRV(" SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); - usbd_edpt_stall(rhport, p_msc->ep_in); - } else { - TU_ASSERT(send_csw(p_msc)); - } - } + msc_cbw_t const *p_cbw = &p_msc->cbw; - #if TU_CHECK_MCU(OPT_MCU_CXD56) - // WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD. - // There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and - // hope everything will work - if ( usbd_edpt_stalled(rhport, p_msc->ep_in) ) { - usbd_edpt_clear_stall(rhport, p_msc->ep_in); - send_csw(p_msc); + // skip status if epin is currently stalled, will do it when received Clear Stall request + if (!usbd_edpt_stalled(rhport, p_msc->ep_in)) { + if ((p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir)) { + // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status + // TU_LOG_DRV(" SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); + usbd_edpt_stall(rhport, p_msc->ep_in); + } else { + TU_ASSERT(send_csw(p_msc)); } - #endif - return true; + } + + #if TU_CHECK_MCU(OPT_MCU_CXD56) + // WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD. + // There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and + // hope everything will work + if (usbd_edpt_stalled(rhport, p_msc->ep_in)) { + usbd_edpt_clear_stall(rhport, p_msc->ep_in); + send_csw(p_msc); + } + #endif + return true; } //--------------------------------------------------------------------+ @@ -258,39 +249,57 @@ bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, u return true; } -static inline void set_sense_medium_not_present(uint8_t lun) { +TU_ATTR_ALWAYS_INLINE static inline void set_sense_medium_not_present(uint8_t lun) { // default sense is NOT READY, MEDIUM NOT PRESENT tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); } -void tud_msc_async_io_done(int32_t bytes_processed) { - // Precheck to avoid queueing multiple RW done callback - TU_VERIFY(_mscd_itf.next_op != MSC_NEXT_OP_NONE,); - // Call usbd_edpt_xfer() in tud_task() to avoid racing condition - usbd_defer_func(tud_msc_async_io_done_cb, (void*) (intptr_t)bytes_processed, false); +static void proc_async_io_done(void *bytes_processed) { + mscd_interface_t *p_msc = &_mscd_itf; + TU_VERIFY(p_msc->pending_io, ); + const int32_t nbytes = (int32_t) (intptr_t) bytes_processed; + const uint8_t cmd = p_msc->cbw.command[0]; + + p_msc->pending_io = 0; + switch (cmd) { + case SCSI_CMD_READ_10: + proc_read_io_data(p_msc, nbytes); + break; + + case SCSI_CMD_WRITE_10: + proc_write_io_data(p_msc, (uint32_t) nbytes, nbytes); + break; + + default: break; + } + + // send status if stage is transitioned to STATUS + if (p_msc->stage == MSC_STAGE_STATUS) { + proc_stage_status(p_msc); + } } -static void tud_msc_async_io_done_cb(void* bytes_processed) { - TU_VERIFY(_mscd_itf.next_op != MSC_NEXT_OP_NONE,); - uint8_t next_op = _mscd_itf.next_op; - _mscd_itf.next_op = MSC_NEXT_OP_NONE; - int32_t nbytes = (int32_t)(intptr_t)bytes_processed; - // READ10 - if (next_op == MSC_NEXT_OP_READ10) { - proc_read10_next(&_mscd_itf, nbytes); - } else if (next_op == MSC_NEXT_OP_WRITE10) { - proc_write10_next(&_mscd_itf, _mscd_itf.xferred_bytes, nbytes); - // Need to manually invoke CSW transfer - if (_mscd_itf.stage == MSC_STAGE_STATUS) { - proc_stage_status(&_mscd_itf); - } +bool tud_msc_async_io_done(int32_t bytes_io, bool in_isr) { + // Precheck to avoid queueing multiple RW done callback + TU_VERIFY(_mscd_itf.pending_io); + if (bytes_io == 0) { + bytes_io = TUD_MSC_RET_ERROR; // 0 is treated as error, no sense to call this with BUSY here } + + if (in_isr) { + usbd_defer_func(proc_async_io_done, (void*) (intptr_t)bytes_io, in_isr); + } else { + proc_async_io_done((void*)(intptr_t) bytes_io); + } + + return true; } //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ void mscd_init(void) { + TU_LOG_INT(CFG_TUD_MSC_LOG_LEVEL, sizeof(mscd_interface_t)); tu_memclr(&_mscd_itf, sizeof(mscd_interface_t)); } @@ -528,7 +537,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t proc_read10_cmd(p_msc); } } else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) { - proc_write10_new_data(p_msc, xferred_bytes); + proc_write10_host_data(p_msc, xferred_bytes); } else { p_msc->xferred_len += xferred_bytes; @@ -560,7 +569,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t break; case MSC_STAGE_STATUS_SENT: - // Wait for the Status phase to complete + // Status phase is complete if ((ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t))) { TU_LOG_DRV(" SCSI Status [Lun%u] = %u\r\n", p_cbw->lun, p_csw->status); // TU_LOG_MEM(CFG_TUD_MSC_LOG_LEVEL, p_csw, xferred_bytes, 2); @@ -590,7 +599,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT(prepare_cbw(p_msc)); } else { - // Any xfer ended here is consider unknown error, ignore it + // Any xfer ended here is considered unknown error, ignore it TU_LOG1(" Warning expect SCSI Status but received unknown data\r\n"); } break; @@ -696,8 +705,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ break; case SCSI_CMD_READ_FORMAT_CAPACITY: { - scsi_read_format_capacity_data_t read_fmt_capa = - { + scsi_read_format_capacity_data_t read_fmt_capa = { .list_length = 8, .block_num = 0, .descriptor_type = 2, // formatted media @@ -729,8 +737,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ break; case SCSI_CMD_INQUIRY: { - scsi_inquiry_resp_t inquiry_rsp = - { + scsi_inquiry_resp_t inquiry_rsp = { .is_removable = 1, .version = 2, .response_data_format = 2, @@ -750,8 +757,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ break; case SCSI_CMD_MODE_SENSE_6: { - scsi_mode_sense6_resp_t mode_resp = - { + scsi_mode_sense6_resp_t mode_resp = { .data_len = 3, .medium_type = 0, .write_protected = false, @@ -772,8 +778,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ break; case SCSI_CMD_REQUEST_SENSE: { - scsi_sense_fixed_resp_t sense_rsp = - { + scsi_sense_fixed_resp_t sense_rsp = { .response_code = 0x70, // current, fixed format .valid = 1 }; @@ -805,32 +810,27 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ static void proc_read10_cmd(mscd_interface_t* p_msc) { msc_cbw_t const* p_cbw = &p_msc->cbw; - - // block size already verified not zero - uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); - - // Adjust lba with transferred bytes + uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); // already verified non-zero + // Adjust lba & offset with transferred bytes uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); + uint32_t const offset = p_msc->xferred_len % block_sz; // remaining bytes capped at class buffer int32_t nbytes = (int32_t)tu_min32(CFG_TUD_MSC_EP_BUFSIZE, p_cbw->total_bytes - p_msc->xferred_len); - // Application can consume smaller bytes - uint32_t const offset = p_msc->xferred_len % block_sz; - - p_msc->next_op = MSC_NEXT_OP_READ10; + p_msc->pending_io = 1; nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, (uint32_t)nbytes); if (nbytes != TUD_MSC_RET_ASYNC) { - p_msc->next_op = MSC_NEXT_OP_NONE; - proc_read10_next(p_msc, nbytes); + p_msc->pending_io = 0; + proc_read_io_data(p_msc, nbytes); } } -static void proc_read10_next(mscd_interface_t* p_msc, int32_t nbytes) { +static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes) { uint8_t rhport = p_msc->rhport; if (nbytes < 0) { // negative means error -> endpoint is stalled & status in CSW set to failed - TU_LOG_DRV(" tud_msc_read10_cb() return -1\r\n"); + TU_LOG_DRV(" IO read() failed\r\n"); // set sense msc_cbw_t const* p_cbw = &p_msc->cbw; @@ -838,7 +838,7 @@ static void proc_read10_next(mscd_interface_t* p_msc, int32_t nbytes) { fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); } else if (nbytes == 0) { - // zero means not ready -> simulate an transfer complete so that this driver callback will fired again + // zero means not ready -> fake a transfer complete so that this driver callback will fire again dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false); } else { TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) nbytes),); @@ -864,55 +864,42 @@ static void proc_write10_cmd(mscd_interface_t* p_msc) { // remaining bytes capped at class buffer uint16_t nbytes = (uint16_t)tu_min32(CFG_TUD_MSC_EP_BUFSIZE, p_cbw->total_bytes - p_msc->xferred_len); // Write10 callback will be called later when usb transfer complete - uint8_t rhport = p_msc->rhport; - TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, nbytes),); + TU_ASSERT(usbd_edpt_xfer(p_msc->rhport, p_msc->ep_out, _mscd_epbuf.buf, nbytes),); } // process new data arrived from WRITE10 -static void proc_write10_new_data(mscd_interface_t* p_msc, uint32_t xferred_bytes) { +static void proc_write10_host_data(mscd_interface_t* p_msc, uint32_t xferred_bytes) { msc_cbw_t const* p_cbw = &p_msc->cbw; + uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); // already verified non-zero - // block size already verified not zero - uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); - - // Adjust lba with transferred bytes + // Adjust lba & offset with transferred bytes uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz); - - // Invoke callback to consume new data uint32_t const offset = p_msc->xferred_len % block_sz; - p_msc->next_op = MSC_NEXT_OP_WRITE10; - p_msc->xferred_bytes = xferred_bytes; + p_msc->pending_io = 1; int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, xferred_bytes); if (nbytes != TUD_MSC_RET_ASYNC) { - p_msc->next_op = MSC_NEXT_OP_NONE; - proc_write10_next(p_msc, xferred_bytes, nbytes); + p_msc->pending_io = 0; + proc_write_io_data(p_msc, xferred_bytes, nbytes); } } -static void proc_write10_next(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes) { +static void proc_write_io_data(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes) { if (nbytes < 0) { // negative means error -> failed this scsi op - TU_LOG_DRV(" tud_msc_write10_cb() return -1\r\n"); - - // update actual byte before failed - p_msc->xferred_len += xferred_bytes; - - msc_cbw_t const* p_cbw = &p_msc->cbw; - set_sense_medium_not_present(p_cbw->lun); + TU_LOG_DRV(" IO write() failed\r\n"); + set_sense_medium_not_present(p_msc->cbw.lun); fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); } else { if ((uint32_t)nbytes < xferred_bytes) { // Application consume less than what we got (including zero) const uint32_t left_over = xferred_bytes - (uint32_t)nbytes; if (nbytes > 0) { - p_msc->xferred_len += (uint16_t)nbytes; memmove(_mscd_epbuf.buf, _mscd_epbuf.buf + nbytes, left_over); } - // simulate a transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter - uint8_t rhport = p_msc->rhport; - dcd_event_xfer_complete(rhport, p_msc->ep_out, left_over, XFER_RESULT_SUCCESS, false); + // fake a transfer complete with adjusted parameters --> callback will be invoked with adjusted parameters + dcd_event_xfer_complete(p_msc->rhport, p_msc->ep_out, left_over, XFER_RESULT_SUCCESS, false); } else { // Application consume all bytes in our buffer p_msc->xferred_len += xferred_bytes; diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 7162b11e4..2ad31c245 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -49,10 +49,11 @@ #endif // Return value of callback functions -// Error -#define TUD_MSC_RET_ERROR -1 -// Asynchronous IO -#define TUD_MSC_RET_ASYNC -16 +enum { + TUD_MSC_RET_BUSY = 0, // Busy, e.g disk I/O is not ready + TUD_MSC_RET_ERROR = -1, + TUD_MSC_RET_ASYNC = -2, // Asynchronous IO +}; TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); @@ -63,54 +64,31 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct"); // Set SCSI sense response bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier); -// Called once asynchronous read/write operation is done -// bytes_processed has the same meaning of tud_msc_read10_cb() / -// tud_msc_write10_cb() return value -void tud_msc_async_io_done(int32_t bytes_processed); +// Called by Application once asynchronous I/O operation is done +// bytes_io is number of bytes in I/O op, typically the bufsize in read/write_cb() or +// TUD_MSC_RET_ERROR (-1) for error. Note TUD_MSC_RET_BUSY (0) will be treated as error as well. +bool tud_msc_async_io_done(int32_t bytes_io, bool in_isr); //--------------------------------------------------------------------+ // Application Callbacks (WEAK is optional) //--------------------------------------------------------------------+ -// Invoked when received SCSI READ10 command -// - Address = lba * BLOCK_SIZE + offset -// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. -// -// - Application fill the buffer (up to bufsize) with address contents and return number of bytes read or status. -// -// - ret < bufsize : These bytes are transferred first and callback will be invoked again for remaining data. -// -// - ret == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback will be invoked again with the same parameters later on. -// -// - ret == TUD_MSC_RET_ERROR (-1) -// : Indicate application error e.g invalid address. This request will be STALLed -// and return failed status in command status wrapper phase. -// -// - ret == TUD_MSC_RET_ASYNC (-16) -// : Data reading will be done asynchronously in a background task. Application should return immediately. -// tud_msc_async_io_done() must be called once reading is done to signal completion. +/* + Invoked when received SCSI READ10/WRITE10 command + - Address = lba * BLOCK_SIZE + offset + - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. + - Application fill the buffer (up to bufsize) with address contents and return number of bytes read or status. + - 0 < ret < bufsize: These bytes are transferred first and callback will be invoked again for remaining data. + - ret == TUD_MSC_RET_BUSY + Application is buys e.g disk I/O not ready. + Callback will be invoked again with the same parameters later on. + - ret == TUD_MSC_RET_ERROR + error such as invalid address. This request will be STALLed and scsi command will be failed + - ret == TUD_MSC_RET_ASYNC + Data I/O will be done asynchronously in a background task. Application should return immediately. + tud_msc_async_io_done() must be called once IO/ is done to signal completion. +*/ int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize); - -// Invoked when received SCSI WRITE10 command -// - Address = lba * BLOCK_SIZE + offset -// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. -// -// - Application writes data from buffer to address contents (up to bufsize) and returns the number of bytes written or status. -// -// - ret < bufsize : Callback will be invoked again with remaining data later on. -// -// - ret == 0 : Indicate application is not ready yet e.g disk I/O busy. -// Callback will be invoked again with the same parameters later on. -// -// - ret == TUD_MSC_RET_ERROR (-1) -// : Indicate application error e.g invalid address. This request will be STALLed -// and return failed status in command status wrapper phase. -// -// - ret == TUD_MSC_RET_ASYNC (-16) -// : Data writing will be done asynchronously in a background task. Application should return immediately. -// tud_msc_async_io_done() must be called once writing is done to signal completion. -// TODO change buffer to const uint8_t* int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); // Invoked when received SCSI_CMD_INQUIRY From 216a35e59a095e6ccb70f7c9bd4f7bc737f44140 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 1 Jul 2025 20:15:16 +0700 Subject: [PATCH 247/382] update example --- .../device/cdc_msc_freertos/src/msc_disk.c | 117 ++++++++---------- .../device/cdc_msc_freertos/src/tusb_config.h | 6 - src/class/msc/msc_device.c | 6 +- 3 files changed, 55 insertions(+), 74 deletions(-) diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index c2aaca847..d1ff2f71b 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -28,8 +28,13 @@ #if CFG_TUD_MSC -#if CFG_EXAMPLE_MSC_ASYNC_IO +// Use async IO in example or not +#define CFG_EXAMPLE_MSC_ASYNC_IO 1 +// Simulate read/write operation delay +#define CFG_EXAMPLE_MSC_IO_DELAY_MS 0 + +#if CFG_EXAMPLE_MSC_ASYNC_IO #define IO_STACK_SIZE configMINIMAL_STACK_SIZE typedef struct { @@ -66,8 +71,7 @@ static bool ejected = false; If you find any bugs or get any questions, feel free to file an\r\n\ issue at github.com/hathach/tinyusb" -enum -{ +enum { DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount DISK_BLOCK_SIZE = 512 }; @@ -162,18 +166,20 @@ static void io_task(void *params) { io_ops_t io_ops; while (1) { if (xQueueReceive(io_queue, &io_ops, portMAX_DELAY)) { + const uint8_t* addr = msc_disk[io_ops.lba] + io_ops.offset; + int32_t nbytes = io_ops.bufsize; if (io_ops.is_read) { - uint8_t const* addr = msc_disk[io_ops.lba] + io_ops.offset; memcpy(io_ops.buffer, addr, io_ops.bufsize); } else { #ifndef CFG_EXAMPLE_MSC_READONLY - uint8_t* addr = msc_disk[io_ops.lba] + io_ops.offset; - memcpy(addr, io_ops.buffer, io_ops.bufsize); + memcpy((uint8_t*) addr, io_ops.buffer, io_ops.bufsize); +#else + nbytes = -1; // failed to write #endif } tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); - tud_msc_async_io_done(io_ops.bufsize); + tud_msc_async_io_done(nbytes, false); } } } @@ -184,14 +190,11 @@ void msc_disk_init() {} // Invoked when received SCSI_CMD_INQUIRY // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively -void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) -{ +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) { (void) lun; - const char vid[] = "TinyUSB"; const char pid[] = "Mass Storage"; const char rev[] = "1.0"; - memcpy(vendor_id , vid, strlen(vid)); memcpy(product_id , pid, strlen(pid)); memcpy(product_rev, rev, strlen(rev)); @@ -199,8 +202,7 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16 // Invoked when received Test Unit Ready command. // return true allowing host to read/write this LUN e.g SD card inserted -bool tud_msc_test_unit_ready_cb(uint8_t lun) -{ +bool tud_msc_test_unit_ready_cb(uint8_t lun) { (void) lun; // RAM disk is ready until ejected @@ -215,10 +217,8 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) // Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size // Application update block count and block size -void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) -{ +void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) { (void) lun; - *block_count = DISK_BLOCK_NUM; *block_size = DISK_BLOCK_SIZE; } @@ -226,18 +226,14 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz // Invoked when received Start Stop Unit command // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage // - Start = 1 : active mode, if load_eject = 1 : load disk storage -bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) -{ +bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) { (void) lun; (void) power_condition; - if ( load_eject ) - { - if (start) - { + if (load_eject) { + if (start) { // load disk storage - }else - { + } else { // unload disk storage ejected = true; } @@ -248,116 +244,107 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo // Callback invoked when received READ10 command. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. -int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) -{ +int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { (void) lun; // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) { + if (lba >= DISK_BLOCK_NUM) { return TUD_MSC_RET_ERROR; } // Check for overflow of offset + bufsize - if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) { + if (lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE) { return TUD_MSC_RET_ERROR; } -#if CFG_EXAMPLE_MSC_ASYNC_IO - io_ops_t io_ops = { .is_read = true, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize }; + #if CFG_EXAMPLE_MSC_ASYNC_IO + io_ops_t io_ops = {.is_read = true, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize}; // Send IO operation to IO task TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS); return TUD_MSC_RET_ASYNC; -#else - uint8_t const* addr = msc_disk[lba] + offset; + #else + uint8_t const *addr = msc_disk[lba] + offset; memcpy(buffer, addr, bufsize); - tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); - return bufsize; -#endif + #endif } -bool tud_msc_is_writable_cb (uint8_t lun) -{ +bool tud_msc_is_writable_cb (uint8_t lun) { (void) lun; -#ifdef CFG_EXAMPLE_MSC_READONLY + #ifdef CFG_EXAMPLE_MSC_READONLY return false; -#else + #else return true; -#endif + #endif } // Callback invoked when received WRITE10 command. // Process data in buffer to disk's storage and return number of written bytes -int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) -{ +int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) { + if (lba >= DISK_BLOCK_NUM) { return TUD_MSC_RET_ERROR; } // Check for overflow of offset + bufsize - if ( lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE ) { + if (lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE) { return TUD_MSC_RET_ERROR; } -#ifdef CFG_EXAMPLE_MSC_READONLY - (void) lun; (void) buffer; + #ifdef CFG_EXAMPLE_MSC_READONLY + (void) lun; + (void) buffer; return bufsize; -#endif + #endif -#if CFG_EXAMPLE_MSC_ASYNC_IO - io_ops_t io_ops = { .is_read = false, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize }; + #if CFG_EXAMPLE_MSC_ASYNC_IO + io_ops_t io_ops = {.is_read = false, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize}; // Send IO operation to IO task TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS); return TUD_MSC_RET_ASYNC; -#else - uint8_t* addr = msc_disk[lba] + offset; + #else + uint8_t *addr = msc_disk[lba] + offset; memcpy(addr, buffer, bufsize); tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS); return bufsize; -#endif + #endif } // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE // - READ10 and WRITE10 has their own callbacks -int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) -{ +int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) { // read10 & write10 has their own callback and MUST not be handled here - void const* response = NULL; + void const *response = NULL; int32_t resplen = 0; // most scsi handled is input bool in_xfer = true; - switch (scsi_cmd[0]) - { + switch (scsi_cmd[0]) { default: // Set Sense = Invalid Command Operation tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // negative means error -> tinyusb could stall and/or response with failed status resplen = -1; - break; + break; } // return resplen must not larger than bufsize - if ( resplen > bufsize ) resplen = bufsize; + if (resplen > bufsize) { resplen = bufsize; } - if ( response && (resplen > 0) ) - { - if(in_xfer) - { + if (response && (resplen > 0)) { + if (in_xfer) { memcpy(buffer, response, (size_t) resplen); - }else - { + } else { // SCSI output } } diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index d70456287..c3f2f7fb5 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -114,12 +114,6 @@ // MSC Buffer size of Device Mass storage #define CFG_TUD_MSC_EP_BUFSIZE 512 -// Use async IO in example or not -#define CFG_EXAMPLE_MSC_ASYNC_IO 1 - -// Simulate read/write operation delay -#define CFG_EXAMPLE_MSC_IO_DELAY_MS 0 - #ifdef __cplusplus } #endif diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 709734b87..a8c52b6bd 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -828,8 +828,8 @@ static void proc_read10_cmd(mscd_interface_t* p_msc) { static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes) { uint8_t rhport = p_msc->rhport; - if (nbytes < 0) { - // negative means error -> endpoint is stalled & status in CSW set to failed + if (nbytes == TUD_MSC_RET_ERROR) { + // error -> endpoint is stalled & status in CSW set to failed TU_LOG_DRV(" IO read() failed\r\n"); // set sense @@ -837,7 +837,7 @@ static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes) { set_sense_medium_not_present(p_cbw->lun); fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); - } else if (nbytes == 0) { + } else if (nbytes == TUD_MSC_RET_BUSY) { // zero means not ready -> fake a transfer complete so that this driver callback will fire again dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false); } else { From c96cc4369f1b97efe85575f3e5633e38598e9fc2 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 1 Jul 2025 21:52:57 +0700 Subject: [PATCH 248/382] defer proc_async_io_done() --- src/class/msc/msc_device.c | 64 +++++++++++++++++++++----------------- src/class/msc/msc_device.h | 9 +++--- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index a8c52b6bd..747ad03ed 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -254,10 +254,10 @@ TU_ATTR_ALWAYS_INLINE static inline void set_sense_medium_not_present(uint8_t lu tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); } -static void proc_async_io_done(void *bytes_processed) { +static void proc_async_io_done(void *bytes_io) { mscd_interface_t *p_msc = &_mscd_itf; TU_VERIFY(p_msc->pending_io, ); - const int32_t nbytes = (int32_t) (intptr_t) bytes_processed; + const int32_t nbytes = (int32_t) (intptr_t) bytes_io; const uint8_t cmd = p_msc->cbw.command[0]; p_msc->pending_io = 0; @@ -283,15 +283,9 @@ bool tud_msc_async_io_done(int32_t bytes_io, bool in_isr) { // Precheck to avoid queueing multiple RW done callback TU_VERIFY(_mscd_itf.pending_io); if (bytes_io == 0) { - bytes_io = TUD_MSC_RET_ERROR; // 0 is treated as error, no sense to call this with BUSY here + bytes_io = TUD_MSC_RET_ERROR; // 0 is treated as error, no reason to call this with BUSY here } - - if (in_isr) { - usbd_defer_func(proc_async_io_done, (void*) (intptr_t)bytes_io, in_isr); - } else { - proc_async_io_done((void*)(intptr_t) bytes_io); - } - + usbd_defer_func(proc_async_io_done, (void *) (intptr_t) bytes_io, in_isr); return true; } @@ -827,21 +821,26 @@ static void proc_read10_cmd(mscd_interface_t* p_msc) { } static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes) { - uint8_t rhport = p_msc->rhport; - if (nbytes == TUD_MSC_RET_ERROR) { - // error -> endpoint is stalled & status in CSW set to failed - TU_LOG_DRV(" IO read() failed\r\n"); - - // set sense - msc_cbw_t const* p_cbw = &p_msc->cbw; - set_sense_medium_not_present(p_cbw->lun); - - fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); - } else if (nbytes == TUD_MSC_RET_BUSY) { - // zero means not ready -> fake a transfer complete so that this driver callback will fire again - dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false); - } else { + const uint8_t rhport = p_msc->rhport; + if (nbytes > 0) { TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) nbytes),); + } else { + // nbytes is status + switch (nbytes) { + case TUD_MSC_RET_ERROR: + // error -> endpoint is stalled & status in CSW set to failed + TU_LOG_DRV(" IO read() failed\r\n"); + set_sense_medium_not_present(p_msc->cbw.lun); + fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); + break; + + case TUD_MSC_RET_BUSY: + // not ready yet -> fake a transfer complete so that this driver callback will fire again + dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false); + break; + + default: break; + } } } @@ -886,13 +885,20 @@ static void proc_write10_host_data(mscd_interface_t* p_msc, uint32_t xferred_byt static void proc_write_io_data(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes) { if (nbytes < 0) { - // negative means error -> failed this scsi op - TU_LOG_DRV(" IO write() failed\r\n"); - set_sense_medium_not_present(p_msc->cbw.lun); - fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); + // nbytes is status + switch (nbytes) { + case TUD_MSC_RET_ERROR: + // IO error -> failed this scsi op + TU_LOG_DRV(" IO write() failed\r\n"); + set_sense_medium_not_present(p_msc->cbw.lun); + fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED); + break; + + default: break; + } } else { if ((uint32_t)nbytes < xferred_bytes) { - // Application consume less than what we got (including zero) + // Application consume less than what we got including TUD_MSC_RET_BUSY (0) const uint32_t left_over = xferred_bytes - (uint32_t)nbytes; if (nbytes > 0) { memmove(_mscd_epbuf.buf, _mscd_epbuf.buf + nbytes, left_over); diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 2ad31c245..f2ea256b4 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -79,12 +79,11 @@ bool tud_msc_async_io_done(int32_t bytes_io, bool in_isr); - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE. - Application fill the buffer (up to bufsize) with address contents and return number of bytes read or status. - 0 < ret < bufsize: These bytes are transferred first and callback will be invoked again for remaining data. - - ret == TUD_MSC_RET_BUSY - Application is buys e.g disk I/O not ready. - Callback will be invoked again with the same parameters later on. - - ret == TUD_MSC_RET_ERROR + - TUD_MSC_RET_BUSY + Application is buys e.g disk I/O not ready. Callback will be invoked again with the same parameters later on. + - TUD_MSC_RET_ERROR error such as invalid address. This request will be STALLed and scsi command will be failed - - ret == TUD_MSC_RET_ASYNC + - TUD_MSC_RET_ASYNC Data I/O will be done asynchronously in a background task. Application should return immediately. tud_msc_async_io_done() must be called once IO/ is done to signal completion. */ From a42184b6fec468e8524b1f1152bed4285a79cfc7 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Jul 2025 11:02:37 +0700 Subject: [PATCH 249/382] remove legacy DEPS_SUBMODULES in make --- examples/device/net_lwip_webserver/Makefile | 2 -- hw/bsp/brtmm90x/family.mk | 1 - hw/bsp/ch32f20x/family.mk | 1 - hw/bsp/espressif/family.mk | 2 -- hw/bsp/imxrt/family.mk | 1 - hw/bsp/kinetis_k/family.mk | 1 - hw/bsp/kinetis_kl/family.mk | 1 - hw/bsp/lpc13/boards/lpcxpresso1347/board.mk | 2 -- hw/bsp/lpc13/family.mk | 2 -- hw/bsp/lpc15/family.mk | 2 -- hw/bsp/lpc17/family.mk | 2 -- hw/bsp/lpc18/family.mk | 1 - hw/bsp/lpc40/family.mk | 2 -- hw/bsp/lpc43/family.mk | 1 - hw/bsp/lpc54/family.mk | 1 - hw/bsp/lpc55/family.mk | 1 - hw/bsp/mcx/family.mk | 2 -- hw/bsp/msp430/family.mk | 1 - hw/bsp/nutiny_nuc121s/board.mk | 2 -- hw/bsp/nutiny_nuc125s/board.mk | 2 -- hw/bsp/nutiny_nuc126v/board.mk | 2 -- hw/bsp/nutiny_sdk_nuc120/board.mk | 2 -- hw/bsp/nutiny_sdk_nuc505/board.mk | 2 -- hw/bsp/rp2040/family.mk | 2 -- hw/bsp/rx/family.mk | 2 -- hw/bsp/same70_qmtech/board.mk | 1 - hw/bsp/same70_xplained/board.mk | 1 - hw/bsp/sltb009a/board.mk | 3 --- hw/bsp/spresense/board.mk | 2 -- hw/bsp/stm32c0/family.mk | 2 -- hw/bsp/stm32f0/family.mk | 2 -- hw/bsp/stm32f1/family.mk | 2 -- hw/bsp/stm32f2/family.mk | 5 ----- hw/bsp/stm32f7/family.mk | 1 - hw/bsp/stm32g0/family.mk | 1 - hw/bsp/stm32l4/family.mk | 1 - hw/bsp/stm32u5/family.mk | 1 - hw/bsp/xmc4000/family.mk | 2 -- test/fuzz/device/net/Makefile | 2 -- test/fuzz/rules.mk | 2 +- 40 files changed, 1 insertion(+), 67 deletions(-) diff --git a/examples/device/net_lwip_webserver/Makefile b/examples/device/net_lwip_webserver/Makefile index 141532466..4ad110dec 100644 --- a/examples/device/net_lwip_webserver/Makefile +++ b/examples/device/net_lwip_webserver/Makefile @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += lib/lwip - include ../../build_system/make/make.mk # suppress warning caused by lwip diff --git a/hw/bsp/brtmm90x/family.mk b/hw/bsp/brtmm90x/family.mk index 6df0bfdfe..2de4dc760 100644 --- a/hw/bsp/brtmm90x/family.mk +++ b/hw/bsp/brtmm90x/family.mk @@ -13,7 +13,6 @@ else # The submodule BRTSG-FOSS/ft90x-sdk contains header files and source # code for the Bridgetek SDK. This can be used instead of the prebuilt # library. -DEPS_SUBMODULES += hw/mcu/bridgetek/ft9xx/ft90x-sdk # The SDK can be used to load specific files from the Bridgetek SDK. FT9XX_SDK = hw/mcu/bridgetek/ft9xx/ft90x-sdk/Source INC += "$(TOP)/$(FT9XX_SDK)/include" diff --git a/hw/bsp/ch32f20x/family.mk b/hw/bsp/ch32f20x/family.mk index c08451b9c..2ff9f79e3 100644 --- a/hw/bsp/ch32f20x/family.mk +++ b/hw/bsp/ch32f20x/family.mk @@ -1,6 +1,5 @@ # Submodules CH32F20X_SDK = hw/mcu/wch/ch32f20x -DEPS_SUBMODULES += $(CH32F20X_SDK) # WCH-SDK paths CH32F20X_SDK_SRC = $(CH32F20X_SDK)/EVT/EXAM/SRC diff --git a/hw/bsp/espressif/family.mk b/hw/bsp/espressif/family.mk index 0dc21b8eb..d955a2b4c 100644 --- a/hw/bsp/espressif/family.mk +++ b/hw/bsp/espressif/family.mk @@ -1,5 +1,3 @@ -#DEPS_SUBMODULES += - UF2_FAMILY_ID_esp32s2 = 0xbfdd4eee UF2_FAMILY_ID_esp32s3 = 0xc47e5767 diff --git a/hw/bsp/imxrt/family.mk b/hw/bsp/imxrt/family.mk index 0cf84a4ae..9a2c37121 100644 --- a/hw/bsp/imxrt/family.mk +++ b/hw/bsp/imxrt/family.mk @@ -1,6 +1,5 @@ UF2_FAMILY_ID = 0x4fb2d5bd SDK_DIR = hw/mcu/nxp/mcux-sdk -DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5 include $(TOP)/$(BOARD_PATH)/board.mk diff --git a/hw/bsp/kinetis_k/family.mk b/hw/bsp/kinetis_k/family.mk index 844ce332e..e95cdb717 100644 --- a/hw/bsp/kinetis_k/family.mk +++ b/hw/bsp/kinetis_k/family.mk @@ -1,5 +1,4 @@ SDK_DIR = hw/mcu/nxp/mcux-sdk -DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5 MCU_DIR = $(SDK_DIR)/devices/${MCU_VARIANT} include $(TOP)/$(BOARD_PATH)/board.mk diff --git a/hw/bsp/kinetis_kl/family.mk b/hw/bsp/kinetis_kl/family.mk index 1fdce981a..8d113aecf 100644 --- a/hw/bsp/kinetis_kl/family.mk +++ b/hw/bsp/kinetis_kl/family.mk @@ -1,5 +1,4 @@ SDK_DIR = hw/mcu/nxp/mcux-sdk -DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5 MCU_DIR = $(SDK_DIR)/devices/$(MCU) include $(TOP)/$(BOARD_PATH)/board.mk diff --git a/hw/bsp/lpc13/boards/lpcxpresso1347/board.mk b/hw/bsp/lpc13/boards/lpcxpresso1347/board.mk index 31eb2f28f..8513c24ca 100644 --- a/hw/bsp/lpc13/boards/lpcxpresso1347/board.mk +++ b/hw/bsp/lpc13/boards/lpcxpresso1347/board.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nxp/lpcopen - CFLAGS += \ -DCFG_TUSB_MEM_SECTION='__attribute__((section(".data.$$RAM2")))' diff --git a/hw/bsp/lpc13/family.mk b/hw/bsp/lpc13/family.mk index 4f8b48c4b..7ff2c058a 100644 --- a/hw/bsp/lpc13/family.mk +++ b/hw/bsp/lpc13/family.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nxp/lpcopen - MCU_DIR = hw/mcu/nxp/lpcopen/lpc13xx/lpc_chip_13xx include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m3 diff --git a/hw/bsp/lpc15/family.mk b/hw/bsp/lpc15/family.mk index 3b63580c0..3267e973a 100644 --- a/hw/bsp/lpc15/family.mk +++ b/hw/bsp/lpc15/family.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nxp/lpcopen - include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m3 diff --git a/hw/bsp/lpc17/family.mk b/hw/bsp/lpc17/family.mk index 551eb9e62..e8d707ea5 100644 --- a/hw/bsp/lpc17/family.mk +++ b/hw/bsp/lpc17/family.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nxp/lpcopen - MCU_DIR = hw/mcu/nxp/lpcopen/lpc175x_6x/lpc_chip_175x_6x include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m3 diff --git a/hw/bsp/lpc18/family.mk b/hw/bsp/lpc18/family.mk index 87b831255..3bbafed11 100644 --- a/hw/bsp/lpc18/family.mk +++ b/hw/bsp/lpc18/family.mk @@ -1,4 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nxp/lpcopen MCU_DIR = hw/mcu/nxp/lpcopen/lpc18xx/lpc_chip_18xx include $(TOP)/$(BOARD_PATH)/board.mk diff --git a/hw/bsp/lpc40/family.mk b/hw/bsp/lpc40/family.mk index 06155c760..c72631235 100644 --- a/hw/bsp/lpc40/family.mk +++ b/hw/bsp/lpc40/family.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nxp/lpcopen - MCU_DIR = hw/mcu/nxp/lpcopen/lpc40xx/lpc_chip_40xx include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m4 diff --git a/hw/bsp/lpc43/family.mk b/hw/bsp/lpc43/family.mk index 4a2ba6ec3..39be867d1 100644 --- a/hw/bsp/lpc43/family.mk +++ b/hw/bsp/lpc43/family.mk @@ -1,4 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nxp/lpcopen SDK_DIR = hw/mcu/nxp/lpcopen/lpc43xx/lpc_chip_43xx include ${TOP}/${BOARD_PATH}/board.mk diff --git a/hw/bsp/lpc54/family.mk b/hw/bsp/lpc54/family.mk index 8dc70f621..94168f6b2 100644 --- a/hw/bsp/lpc54/family.mk +++ b/hw/bsp/lpc54/family.mk @@ -1,5 +1,4 @@ SDK_DIR = hw/mcu/nxp/mcux-sdk -DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5 include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m4 diff --git a/hw/bsp/lpc55/family.mk b/hw/bsp/lpc55/family.mk index b83942c87..fadf852cd 100644 --- a/hw/bsp/lpc55/family.mk +++ b/hw/bsp/lpc55/family.mk @@ -1,6 +1,5 @@ UF2_FAMILY_ID = 0x2abc77ec SDK_DIR = hw/mcu/nxp/mcux-sdk -DEPS_SUBMODULES += lib/CMSIS_5 lib/sct_neopixel $(SDK_DIR) include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m33 diff --git a/hw/bsp/mcx/family.mk b/hw/bsp/mcx/family.mk index 676475cc9..a16f4b6c0 100644 --- a/hw/bsp/mcx/family.mk +++ b/hw/bsp/mcx/family.mk @@ -1,8 +1,6 @@ UF2_FAMILY_ID = 0x2abc77ec SDK_DIR = hw/mcu/nxp/mcux-sdk -DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5 - include $(TOP)/$(BOARD_PATH)/board.mk # Default to Highspeed PORT1 diff --git a/hw/bsp/msp430/family.mk b/hw/bsp/msp430/family.mk index 06508ab2c..c973d9dcd 100644 --- a/hw/bsp/msp430/family.mk +++ b/hw/bsp/msp430/family.mk @@ -1,5 +1,4 @@ CROSS_COMPILE = msp430-elf- -DEPS_SUBMODULES += hw/mcu/ti SKIP_NANOLIB = 1 SDK_DIR = hw/mcu/ti/msp430/msp430-gcc-support-files/include diff --git a/hw/bsp/nutiny_nuc121s/board.mk b/hw/bsp/nutiny_nuc121s/board.mk index 161ff9041..06c47d544 100644 --- a/hw/bsp/nutiny_nuc121s/board.mk +++ b/hw/bsp/nutiny_nuc121s/board.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nuvoton - CFLAGS += \ -flto \ -mthumb \ diff --git a/hw/bsp/nutiny_nuc125s/board.mk b/hw/bsp/nutiny_nuc125s/board.mk index 081764fd3..50b9d866a 100644 --- a/hw/bsp/nutiny_nuc125s/board.mk +++ b/hw/bsp/nutiny_nuc125s/board.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nuvoton - CFLAGS += \ -flto \ -mthumb \ diff --git a/hw/bsp/nutiny_nuc126v/board.mk b/hw/bsp/nutiny_nuc126v/board.mk index 2466b3a31..e87d1aad0 100644 --- a/hw/bsp/nutiny_nuc126v/board.mk +++ b/hw/bsp/nutiny_nuc126v/board.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nuvoton - CFLAGS += \ -flto \ -mthumb \ diff --git a/hw/bsp/nutiny_sdk_nuc120/board.mk b/hw/bsp/nutiny_sdk_nuc120/board.mk index b54895b58..d982bdc06 100644 --- a/hw/bsp/nutiny_sdk_nuc120/board.mk +++ b/hw/bsp/nutiny_sdk_nuc120/board.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nuvoton - CFLAGS += \ -flto \ -mthumb \ diff --git a/hw/bsp/nutiny_sdk_nuc505/board.mk b/hw/bsp/nutiny_sdk_nuc505/board.mk index f3b389354..1dc8b244e 100644 --- a/hw/bsp/nutiny_sdk_nuc505/board.mk +++ b/hw/bsp/nutiny_sdk_nuc505/board.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/nuvoton - CFLAGS += \ -flto \ -mthumb \ diff --git a/hw/bsp/rp2040/family.mk b/hw/bsp/rp2040/family.mk index 25d1ad9c5..813683c54 100644 --- a/hw/bsp/rp2040/family.mk +++ b/hw/bsp/rp2040/family.mk @@ -1,8 +1,6 @@ JLINK_DEVICE = rp2040_m0_0 PYOCD_TARGET = rp2040 -DEPS_SUBMODULES += hw/mcu/raspberry_pi/Pico-PIO-USB - ifeq ($(DEBUG), 1) CMAKE_DEFSYM += -DCMAKE_BUILD_TYPE=Debug endif diff --git a/hw/bsp/rx/family.mk b/hw/bsp/rx/family.mk index 02ea0dfa4..4ecf80409 100644 --- a/hw/bsp/rx/family.mk +++ b/hw/bsp/rx/family.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/renesas/rx - # Cross Compiler for RX CROSS_COMPILE = rx-elf- diff --git a/hw/bsp/same70_qmtech/board.mk b/hw/bsp/same70_qmtech/board.mk index 281a947f3..7e949e135 100644 --- a/hw/bsp/same70_qmtech/board.mk +++ b/hw/bsp/same70_qmtech/board.mk @@ -1,4 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/microchip ASF_DIR = hw/mcu/microchip/same70 CFLAGS += \ diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk index 60702f14a..2d97ecdc1 100644 --- a/hw/bsp/same70_xplained/board.mk +++ b/hw/bsp/same70_xplained/board.mk @@ -1,4 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/microchip ASF_DIR = hw/mcu/microchip/same70 CFLAGS += \ diff --git a/hw/bsp/sltb009a/board.mk b/hw/bsp/sltb009a/board.mk index 687761364..5dd7a158f 100644 --- a/hw/bsp/sltb009a/board.mk +++ b/hw/bsp/sltb009a/board.mk @@ -16,9 +16,6 @@ CFLAGS += \ SILABS_FAMILY = efm32gg12b SILABS_CMSIS = hw/mcu/silabs/cmsis-dfp-$(SILABS_FAMILY)/Device/SiliconLabs/$(shell echo $(SILABS_FAMILY) | tr a-z A-Z) -DEPS_SUBMODULES += hw/mcu/silabs/cmsis-dfp-$(SILABS_FAMILY) -DEPS_SUBMODULES += lib/CMSIS_5 - LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs # All source paths should be relative to the top level. diff --git a/hw/bsp/spresense/board.mk b/hw/bsp/spresense/board.mk index 15fa0ff20..24f39d2b6 100644 --- a/hw/bsp/spresense/board.mk +++ b/hw/bsp/spresense/board.mk @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += hw/mcu/sony/cxd56/spresense-exported-sdk - # Platforms are: Linux, Darwin, MSYS, CYGWIN PLATFORM := $(firstword $(subst _, ,$(shell uname -s 2>/dev/null))) diff --git a/hw/bsp/stm32c0/family.mk b/hw/bsp/stm32c0/family.mk index 9ff3a2fdf..bdb34454e 100644 --- a/hw/bsp/stm32c0/family.mk +++ b/hw/bsp/stm32c0/family.mk @@ -1,6 +1,4 @@ ST_FAMILY = c0 -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver - ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver diff --git a/hw/bsp/stm32f0/family.mk b/hw/bsp/stm32f0/family.mk index 431709de0..9b8305874 100644 --- a/hw/bsp/stm32f0/family.mk +++ b/hw/bsp/stm32f0/family.mk @@ -1,7 +1,5 @@ UF2_FAMILY_ID = 0x647824b6 ST_FAMILY = f0 -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver - ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver diff --git a/hw/bsp/stm32f1/family.mk b/hw/bsp/stm32f1/family.mk index 364616304..ca95f2315 100644 --- a/hw/bsp/stm32f1/family.mk +++ b/hw/bsp/stm32f1/family.mk @@ -1,6 +1,4 @@ ST_FAMILY = f1 -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_${ST_FAMILY} hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver - ST_CMSIS = hw/mcu/st/cmsis_device_${ST_FAMILY} ST_HAL_DRIVER = hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver diff --git a/hw/bsp/stm32f2/family.mk b/hw/bsp/stm32f2/family.mk index e8f02548d..ef14a9d67 100644 --- a/hw/bsp/stm32f2/family.mk +++ b/hw/bsp/stm32f2/family.mk @@ -2,11 +2,6 @@ ST_FAMILY = f2 ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver -DEPS_SUBMODULES += \ - lib/CMSIS_5 \ - $(ST_CMSIS) \ - $(ST_HAL_DRIVER) - include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m3 diff --git a/hw/bsp/stm32f7/family.mk b/hw/bsp/stm32f7/family.mk index abeea784c..d3422e03c 100644 --- a/hw/bsp/stm32f7/family.mk +++ b/hw/bsp/stm32f7/family.mk @@ -1,6 +1,5 @@ UF2_FAMILY_ID = 0x53b80f00 ST_FAMILY = f7 -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver diff --git a/hw/bsp/stm32g0/family.mk b/hw/bsp/stm32g0/family.mk index 95b8e537d..d735ca92d 100644 --- a/hw/bsp/stm32g0/family.mk +++ b/hw/bsp/stm32g0/family.mk @@ -1,5 +1,4 @@ ST_FAMILY = g0 -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver diff --git a/hw/bsp/stm32l4/family.mk b/hw/bsp/stm32l4/family.mk index 950b6f9cb..01d059236 100644 --- a/hw/bsp/stm32l4/family.mk +++ b/hw/bsp/stm32l4/family.mk @@ -1,5 +1,4 @@ ST_FAMILY = l4 -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk index 7fc728dcf..3694b1ca0 100644 --- a/hw/bsp/stm32u5/family.mk +++ b/hw/bsp/stm32u5/family.mk @@ -1,5 +1,4 @@ ST_FAMILY = u5 -DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver diff --git a/hw/bsp/xmc4000/family.mk b/hw/bsp/xmc4000/family.mk index a1679a2f0..4eed7360a 100644 --- a/hw/bsp/xmc4000/family.mk +++ b/hw/bsp/xmc4000/family.mk @@ -1,8 +1,6 @@ UF2_FAMILY_ID = 0x00 SDK_DIR = hw/mcu/infineon/mtb-xmclib-cat3 -DEPS_SUBMODULES += ${SDK_DIR} - include $(TOP)/$(BOARD_PATH)/board.mk CPU_CORE ?= cortex-m4 diff --git a/test/fuzz/device/net/Makefile b/test/fuzz/device/net/Makefile index 4e99604ad..2161ad3f1 100644 --- a/test/fuzz/device/net/Makefile +++ b/test/fuzz/device/net/Makefile @@ -1,5 +1,3 @@ -DEPS_SUBMODULES += lib/lwip - include ../../make.mk # suppress warning caused by lwip diff --git a/test/fuzz/rules.mk b/test/fuzz/rules.mk index ee91c706d..562969663 100644 --- a/test/fuzz/rules.mk +++ b/test/fuzz/rules.mk @@ -142,7 +142,7 @@ endif # get depenecies .PHONY: get-deps get-deps: - $(PYTHON) $(TOP)/tools/get_deps.py $(DEPS_SUBMODULES) + $(PYTHON) $(TOP)/tools/get_deps.py $(FAMILY) size: $(BUILD)/$(PROJECT) -@echo '' From 4579b4f8255a5ed06e276978474fab7c7567445a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Jul 2025 14:41:16 +0700 Subject: [PATCH 250/382] add doc for building examples with cmake build system change ci matrix build: - github build make/cmake one per family on push only - circicle do full cmake build for all toolchain (missing rx-gcc) --- .circleci/config.yml | 9 ++-- .github/workflows/build.yml | 69 +++++++++++++--------------- docs/reference/getting_started.rst | 72 ++++++++++++++++++++---------- hw/bsp/espressif/family.cmake | 2 - hw/bsp/espressif/family.mk | 32 ------------- hw/bsp/msp430/family.cmake | 48 ++++++++++---------- 6 files changed, 107 insertions(+), 125 deletions(-) delete mode 100644 hw/bsp/espressif/family.mk diff --git a/.circleci/config.yml b/.circleci/config.yml index 0b11b50e4..3b4389ab4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,13 +19,12 @@ jobs: echo "MATRIX_JSON=$MATRIX_JSON" BUILDSYSTEM_TOOLCHAIN=( + "cmake aarch64-gcc" "cmake arm-clang" + "cmake arm-gcc" "cmake esp-idf" - "make aarch64-gcc" - "make arm-gcc" - "make msp430-gcc" - "make riscv-gcc" - "make rx-gcc" + "cmake msp430-gcc" + "cmake riscv-gcc" ) # only build IAR if not forked PR, since IAR token is not shared diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fe2ed61c9..58963013b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,11 +36,6 @@ env: HIL_JSON: test/hil/tinyusb.json jobs: - # --------------------------------------- - # - # Build - # - # --------------------------------------- set-matrix: runs-on: ubuntu-latest outputs: @@ -63,28 +58,31 @@ jobs: echo "hil_matrix=$HIL_MATRIX_JSON" >> $GITHUB_OUTPUT # --------------------------------------- - # Build CMake + # Build CMake: only build on push with one-per-family. + # Full built is done by CircleCI in PR # --------------------------------------- cmake: + if: github.event_name == 'push' needs: set-matrix uses: ./.github/workflows/build_util.yml strategy: fail-fast: false matrix: toolchain: - # - 'arm-clang' is built by circle-ci in PR - 'aarch64-gcc' + - 'arm-clang' - 'arm-gcc' + - 'esp-idf' - 'msp430-gcc' - 'riscv-gcc' with: build-system: 'cmake' toolchain: ${{ matrix.toolchain }} build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain]) }} - one-per-family: ${{ github.event_name == 'push' }} + one-per-family: true # --------------------------------------- - # Build Make (built by circle-ci in PR, only build on push here) + # Build Make: only build on push with one-per-family # --------------------------------------- make: if: github.event_name == 'push' @@ -94,19 +92,39 @@ jobs: fail-fast: false matrix: toolchain: - # 'arm-clang' - - 'arm-gcc' - 'aarch64-gcc' + - 'arm-clang' + - 'arm-gcc' - 'msp430-gcc' - 'riscv-gcc' - 'rx-gcc' - - 'esp-idf' with: build-system: 'make' toolchain: ${{ matrix.toolchain }} build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain]) }} one-per-family: true + # --------------------------------------- + # Build IAR + # Since IAR Token secret is not passed to forked PR, only build non-forked PR with make. + # cmake is built by circle-ci. Due to IAR limit capacity, only build oe per family + # --------------------------------------- + arm-iar: + if: github.event_name == 'push' && github.repository_owner == 'hathach' + needs: set-matrix + uses: ./.github/workflows/build_util.yml + secrets: inherit + strategy: + fail-fast: false + matrix: + build-system: + - 'make' + with: + build-system: ${{ matrix.build-system }} + toolchain: 'arm-iar' + build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)['arm-iar']) }} + one-per-family: true + # --------------------------------------- # Build Make on Windows/MacOS # --------------------------------------- @@ -124,28 +142,6 @@ jobs: build-args: '["stm32h7"]' one-per-family: true - # --------------------------------------- - # Build IAR - # Since IAR Token secret is not passed to forked PR, only build non-forked PR with make. - # cmake is built by circle-ci. Due to IAR limit capacity, only build oe per family - # --------------------------------------- - arm-iar: - if: false # disable for now since we got reach capacity limit too often - #if: github.event_name == 'push' && github.repository_owner == 'hathach' - needs: set-matrix - uses: ./.github/workflows/build_util.yml - secrets: inherit - strategy: - fail-fast: false - matrix: - build-system: - - 'make' - with: - build-system: ${{ matrix.build-system }} - toolchain: 'arm-iar' - build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)['arm-iar']) }} - one-per-family: true - # --------------------------------------- # Zephyr # --------------------------------------- @@ -168,14 +164,9 @@ jobs: west build -b pca10056 -d examples/device/msc_dual_lun/build examples/device/msc_dual_lun -- -DRTOS=zephyr # --------------------------------------- - # # Hardware in the loop (HIL) # Run on PR only (hil-tinyusb), hil-hfp only run on non-forked PR # --------------------------------------- - - # --------------------------------------- - # Build arm-gcc - # --------------------------------------- hil-build: if: | github.repository_owner == 'hathach' && diff --git a/docs/reference/getting_started.rst b/docs/reference/getting_started.rst index 37745d6a1..ee68f6386 100644 --- a/docs/reference/getting_started.rst +++ b/docs/reference/getting_started.rst @@ -5,12 +5,12 @@ Getting Started Add TinyUSB to your project --------------------------- -It is relatively simple to incorporate tinyusb to your project +To incorporate tinyusb to your project * Copy or ``git submodule`` this repo into your project in a subfolder. Let's say it is ``your_project/tinyusb`` * Add all the ``.c`` in the ``tinyusb/src`` folder to your project * Add ``your_project/tinyusb/src`` to your include path. Also make sure your current include path also contains the configuration file ``tusb_config.h``. -* Make sure all required macros are all defined properly in ``tusb_config.h`` (configure file in demo application is sufficient, but you need to add a few more such as ``CFG_TUSB_MCU``, ``CFG_TUSB_OS`` since they are passed by IDE/compiler to maintain a unique configure for all boards). +* Make sure all required macros are all defined properly in ``tusb_config.h`` (configure file in demo application is sufficient, but you need to add a few more such as ``CFG_TUSB_MCU``, ``CFG_TUSB_OS`` since they are passed by make/cmake to maintain a unique configure for all boards). * If you use the device stack, make sure you have created/modified usb descriptors for your own need. Ultimately you need to implement all **tud descriptor** callbacks for the stack to work. * Add ``tusb_init(rhport, role)`` call to your reset initialization code. * Call ``tusb_int_handler(rhport, in_isr)`` in your USB IRQ Handler @@ -75,24 +75,36 @@ The hardware code is located in ``hw/bsp`` folder, and is organized by family/bo .. code-block:: bash $ cd examples/device/cdc_msc - $ make BOARD=raspberry_pi_pico get-deps + $ make BOARD=feather_nrf52840_express get-deps You only need to do this once per family. Check out `complete list of dependencies and their designated path here `_ -Build -^^^^^ +Build Examples +^^^^^^^^^^^^^^ -To build example, first change directory to an example folder. +Examples support make and cmake build system, though some MCU family such as espressif/rp2040 only support cmake. First change directory to an example folder. .. code-block:: bash $ cd examples/device/cdc_msc -Then compile with ``make BOARD={board_name} all`` , for example +Then compile with make or cmake .. code-block:: bash - $ make BOARD=raspberry_pi_pico all + $ # make + $ make BOARD=feather_nrf52840_express all + + $ # cmake + $ mkdir build && cd build + $ cmake -DBOARD=raspberry_pi_pico .. + $ make + +To list all available targets with cmake + +.. code-block:: bash + + $ cmake --build . --target help Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``99-tinyusb.rules`` and reload your udev is good to go @@ -104,20 +116,24 @@ Note: some examples especially those that uses Vendor class (e.g webUSB) may req RootHub Port Selection ~~~~~~~~~~~~~~~~~~~~~~ -If a board has several ports, one port is chosen by default in the individual board.mk file. Use option ``PORT=x`` To choose another port. For example to select the HS port of a STM32F746Disco board, use: +If a board has several ports, one port is chosen by default in the individual board.mk file. Use option ``RHPORT_DEVICE=x`` or ``RHPORT_HOST=x`` To choose another port. For example to select the HS port of a STM32F746Disco board, use: .. code-block:: bash - $ make BOARD=stm32f746disco PORT=1 all + $ make BOARD=stm32f746disco RHPORT_DEVICE=1 all + + $ cmake -DBOARD=stm32f746disco -DRHPORT_DEVICE=1 .. Port Speed ~~~~~~~~~~ -A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option ``SPEED=full/high`` e.g To force F723 operate at full instead of default high speed +A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option ``RHPORT_DEVICE_SPEED=OPT_MODE_FULL/HIGH_SPEED/`` or ``RHPORT_HOST_SPEED=OPT_MODE_FULL/HIGH_SPEED/`` e.g To force F723 operate at full instead of default high speed .. code-block:: bash - $ make BOARD=stm32f746disco SPEED=full all + $ make BOARD=stm32f746disco RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED all + + $ cmake -DBOARD=stm32f746disco -DRHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED .. Size Analysis ~~~~~~~~~~~~~ @@ -137,6 +153,8 @@ To compile for debugging add ``DEBUG=1``\ , for example $ make BOARD=feather_nrf52840_express DEBUG=1 all + $ cmake -DBOARD=feather_nrf52840_express -DCMAKE_BUILD_TYPE=Debug .. + Log ~~~ @@ -146,6 +164,8 @@ Should you have an issue running example and/or submitting an bug report. You co $ make BOARD=feather_nrf52840_express LOG=2 all + $ cmake -DBOARD=feather_nrf52840_express -DLOG=2 .. + Logger ~~~~~~ @@ -169,6 +189,9 @@ By default log message is printed via on-board UART which is slow and take lots $ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all $ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all + $ cmake -DBOARD=feather_nrf52840_express -DLOG=2 -DLOGGER=rtt .. + $ cmake -DBOARD=feather_nrf52840_express -DLOG=2 -DLOGGER=swo .. + Flash ^^^^^ @@ -179,11 +202,15 @@ Flash $ make BOARD=feather_nrf52840_express flash $ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash -Since jlink can be used with most of the boards, there is also ``flash-jlink`` target for your convenience. +Since jlink/openocd can be used with most of the boards, there is also ``flash-jlink/openocd`` (make) and ``EXAMPLE-jlink/openocd`` target for your convenience. Note for stm32 board with stlink, you can use ``flash-stlink`` target as well. .. code-block:: bash $ make BOARD=feather_nrf52840_express flash-jlink + $ make BOARD=feather_nrf52840_express flash-openocd + + $ cmake --build . --target cdc_msc-jlink + $ cmake --build . --target cdc_msc-openocd Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with ``uf2`` target @@ -191,17 +218,18 @@ Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can $ make BOARD=feather_nrf52840_express all uf2 + $ cmake --build . --target cdc_msc-uf2 + IAR Support ------------ +^^^^^^^^^^^ Use project connection -^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~ IAR Project Connection files are provided to import TinyUSB stack into your project. * A buildable project of your MCU need to be created in advance. - * Take example of STM32F0: - You need ``stm32l0xx.h``, ``startup_stm32f0xx.s``, ``system_stm32f0xx.c``. @@ -212,15 +240,13 @@ IAR Project Connection files are provided to import TinyUSB stack into your proj Click ``New Group ...``, name it to ``TUSB``, Click ``Add Variable ...``, name it to ``TUSB_DIR``, change it's value to the path of your TinyUSB stack, for example ``C:\\tinyusb`` -Import stack only -~~~~~~~~~~~~~~~~~ +**Import stack only** -1. Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\tools\\iar_template.ipcf``. +Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\tools\\iar_template.ipcf``. -Run examples -~~~~~~~~~~~~ +**Run examples** -1. (Python3 is needed) Run ``iar_gen.py`` to generate .ipcf files of examples: +1. Run ``iar_gen.py`` to generate .ipcf files of examples: .. code-block:: @@ -231,7 +257,7 @@ Run examples For example ``C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf`` Native CMake support (9.50.1+) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ With 9.50.1 release, IAR added experimental native CMake support (strangely not mentioned in public release note). Now it's possible to import CMakeLists.txt then build and debug as a normal project. diff --git a/hw/bsp/espressif/family.cmake b/hw/bsp/espressif/family.cmake index 2aad7d185..ca9eadaf6 100644 --- a/hw/bsp/espressif/family.cmake +++ b/hw/bsp/espressif/family.cmake @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 3.5) - # Apply board specific content i.e IDF_TARGET must be set before project.cmake is included include("${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake") string(TOUPPER ${IDF_TARGET} FAMILY_MCUS) diff --git a/hw/bsp/espressif/family.mk b/hw/bsp/espressif/family.mk deleted file mode 100644 index d955a2b4c..000000000 --- a/hw/bsp/espressif/family.mk +++ /dev/null @@ -1,32 +0,0 @@ -UF2_FAMILY_ID_esp32s2 = 0xbfdd4eee -UF2_FAMILY_ID_esp32s3 = 0xc47e5767 - -BOARD_CMAKE := $(file < $(TOP)/$(BOARD_PATH)/board.cmake) -ifneq ($(findstring esp32s2,$(BOARD_CMAKE)),) - IDF_TARGET = esp32s2 -else -ifneq ($(findstring esp32s3,$(BOARD_CMAKE)),) - IDF_TARGET = esp32s3 -endif -endif - -.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu - -all: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) build - -build: all - -fullclean: - if test -f sdkconfig; then $(RM) -f sdkconfig ; fi - if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@ - -clean flash bootloader-flash app-flash erase monitor dfu-flash dfu size size-components size-files: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@ - -uf2: $(BUILD)/$(PROJECT).uf2 - -$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin - @echo CREATE $@ - $(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID_$(IDF_TARGET)) -b 0x0 -c -o $@ $^ diff --git a/hw/bsp/msp430/family.cmake b/hw/bsp/msp430/family.cmake index ddd54b675..d9b4bf770 100644 --- a/hw/bsp/msp430/family.cmake +++ b/hw/bsp/msp430/family.cmake @@ -11,36 +11,37 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/msp430_${T set(FAMILY_MCUS MSP430x5xx CACHE INTERNAL "") - #------------------------------------ # BOARD_TARGET #------------------------------------ # only need to be built ONCE for all examples function(add_board_target BOARD_TARGET) - if (NOT TARGET ${BOARD_TARGET}) - add_library(${BOARD_TARGET} INTERFACE) - target_compile_definitions(${BOARD_TARGET} INTERFACE - CFG_TUD_ENDPOINT0_SIZE=8 - CFG_EXAMPLE_VIDEO_READONLY - CFG_EXAMPLE_MSC_READONLY - ) - target_include_directories(${BOARD_TARGET} INTERFACE - ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${SDK_DIR} - ) + if (TARGET ${BOARD_TARGET}) + return() + endif () - update_board(${BOARD_TARGET}) + add_library(${BOARD_TARGET} INTERFACE) + target_compile_definitions(${BOARD_TARGET} INTERFACE + CFG_TUD_ENDPOINT0_SIZE=8 + CFG_EXAMPLE_VIDEO_READONLY + CFG_EXAMPLE_MSC_READONLY + ) + target_include_directories(${BOARD_TARGET} INTERFACE + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${SDK_DIR} + ) - if (CMAKE_C_COMPILER_ID STREQUAL "GNU") - target_link_options(${BOARD_TARGET} INTERFACE - "LINKER:--script=${LD_FILE_GNU}" - -L${SDK_DIR} - ) - elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") - target_link_options(${BOARD_TARGET} INTERFACE - "LINKER:--config=${LD_FILE_IAR}" - ) - endif () + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} INTERFACE + "LINKER:--script=${LD_FILE_GNU}" + -L${SDK_DIR} + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} INTERFACE + "LINKER:--config=${LD_FILE_IAR}" + ) endif () endfunction() @@ -75,7 +76,6 @@ function(family_configure_example TARGET RTOS) ) target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - # Flashing family_add_bin_hex(${TARGET}) family_flash_msp430flasher(${TARGET}) From 0388700ad7c0fc8565457a56d7e7bd5744ac0d1d Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Jul 2025 15:32:12 +0700 Subject: [PATCH 251/382] update esp build, replace TUSB_MCU_VENDOR_ESPRESSIF by ESP_PLATFORM --- .github/workflows/build.yml | 2 +- .../device/audio_4_channel_mic_freertos/src/main.c | 11 +++++------ .../audio_4_channel_mic_freertos/src/tusb_config.h | 2 +- examples/device/audio_test_freertos/src/main.c | 8 ++++---- examples/device/audio_test_freertos/src/tusb_config.h | 2 +- examples/device/board_test/src/tusb_config.h | 2 +- examples/device/cdc_msc_freertos/src/main.c | 8 ++++---- examples/device/cdc_msc_freertos/src/tusb_config.h | 2 +- examples/device/hid_composite_freertos/src/main.c | 11 +++++------ .../device/hid_composite_freertos/src/tusb_config.h | 2 +- examples/device/midi_test_freertos/src/main.c | 8 ++++---- examples/device/video_capture/src/main.c | 6 +++--- examples/device/video_capture/src/tusb_config.h | 2 +- examples/device/video_capture_2ch/src/main.c | 6 +++--- examples/device/video_capture_2ch/src/tusb_config.h | 2 +- examples/host/cdc_msc_hid_freertos/src/cdc_app.c | 2 +- examples/host/cdc_msc_hid_freertos/src/main.c | 8 ++++---- examples/host/cdc_msc_hid_freertos/src/tusb_config.h | 2 +- examples/host/device_info/src/main.c | 8 ++++---- examples/host/device_info/src/tusb_config.h | 2 +- examples/host/midi_rx/src/tusb_config.h | 2 +- examples/typec/power_delivery/src/main.c | 5 ++--- hw/bsp/board.c | 7 ++++--- hw/bsp/board_api.h | 3 ++- hw/bsp/espressif/boards/family.c | 4 ++++ tools/build.py | 6 ++---- tools/build_utils.py | 2 ++ 27 files changed, 64 insertions(+), 61 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 58963013b..97f219e6f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -93,7 +93,7 @@ jobs: matrix: toolchain: - 'aarch64-gcc' - - 'arm-clang' + #- 'arm-clang' - 'arm-gcc' - 'msp430-gcc' - 'riscv-gcc' diff --git a/examples/device/audio_4_channel_mic_freertos/src/main.c b/examples/device/audio_4_channel_mic_freertos/src/main.c index 99278b5cc..d5a34b194 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/main.c +++ b/examples/device/audio_4_channel_mic_freertos/src/main.c @@ -39,7 +39,7 @@ #include "bsp/board_api.h" #include "tusb.h" -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" @@ -158,17 +158,16 @@ int main(void) xTaskCreate(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); #endif - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 - #if !TUSB_MCU_VENDOR_ESPRESSIF + // only start scheduler for non-espressif mcu + #ifndef ESP_PLATFORM vTaskStartScheduler(); #endif return 0; } -#if TUSB_MCU_VENDOR_ESPRESSIF -void app_main(void) -{ +#ifdef ESP_PLATFORM +void app_main(void) { main(); } #endif diff --git a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h index 5ac51b153..f7c0efe08 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h +++ b/examples/device/audio_4_channel_mic_freertos/src/tusb_config.h @@ -59,7 +59,7 @@ extern "C" { #endif // Espressif IDF requires "freertos/" prefix in include path -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/audio_test_freertos/src/main.c b/examples/device/audio_test_freertos/src/main.c index c5143c3fc..3831be87f 100644 --- a/examples/device/audio_test_freertos/src/main.c +++ b/examples/device/audio_test_freertos/src/main.c @@ -38,7 +38,7 @@ #include "bsp/board_api.h" #include "tusb.h" -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" @@ -132,15 +132,15 @@ int main(void) xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); #endif - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 - #if !TUSB_MCU_VENDOR_ESPRESSIF + // only start scheduler for non-espressif mcu + #ifndef ESP_PLATFORM vTaskStartScheduler(); #endif return 0; } -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM void app_main(void) { main(); } diff --git a/examples/device/audio_test_freertos/src/tusb_config.h b/examples/device/audio_test_freertos/src/tusb_config.h index 61c5cbb96..0fb2106e2 100644 --- a/examples/device/audio_test_freertos/src/tusb_config.h +++ b/examples/device/audio_test_freertos/src/tusb_config.h @@ -59,7 +59,7 @@ extern "C" { #endif // Espressif IDF requires "freertos/" prefix in include path -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/board_test/src/tusb_config.h b/examples/device/board_test/src/tusb_config.h index 8ac3bc8de..81829d450 100644 --- a/examples/device/board_test/src/tusb_config.h +++ b/examples/device/board_test/src/tusb_config.h @@ -44,7 +44,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 4dada9801..6fe964153 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -30,7 +30,7 @@ #include "bsp/board_api.h" #include "tusb.h" -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define USBD_STACK_SIZE 4096 #else // Increase stack size when debug log is enabled @@ -91,15 +91,15 @@ int main(void) { xTaskCreate(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL); #endif -#if !TUSB_MCU_VENDOR_ESPRESSIF - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 +#ifndef ESP_PLATFORM + // only start scheduler for non-espressif mcu vTaskStartScheduler(); #endif return 0; } -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM void app_main(void) { main(); } diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index c3f2f7fb5..71a0e985a 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -59,7 +59,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/hid_composite_freertos/src/main.c b/examples/device/hid_composite_freertos/src/main.c index 30c0331ef..3f5e8a91c 100644 --- a/examples/device/hid_composite_freertos/src/main.c +++ b/examples/device/hid_composite_freertos/src/main.c @@ -31,7 +31,7 @@ #include "tusb.h" #include "usb_descriptors.h" -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" @@ -112,17 +112,16 @@ int main(void) xTimerStart(blinky_tm, 0); - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 -#if !TUSB_MCU_VENDOR_ESPRESSIF + // only start scheduler for non-espressif mcu +#ifndef ESP_PLATFORM vTaskStartScheduler(); #endif return 0; } -#if TUSB_MCU_VENDOR_ESPRESSIF -void app_main(void) -{ +#ifdef ESP_PLATFORM +void app_main(void) { main(); } #endif diff --git a/examples/device/hid_composite_freertos/src/tusb_config.h b/examples/device/hid_composite_freertos/src/tusb_config.h index 6ec38b95c..b28033a0c 100644 --- a/examples/device/hid_composite_freertos/src/tusb_config.h +++ b/examples/device/hid_composite_freertos/src/tusb_config.h @@ -59,7 +59,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/midi_test_freertos/src/main.c b/examples/device/midi_test_freertos/src/main.c index dbe89080c..3e406d38d 100644 --- a/examples/device/midi_test_freertos/src/main.c +++ b/examples/device/midi_test_freertos/src/main.c @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define USBD_STACK_SIZE 4096 #else // Increase stack size when debug log is enabled @@ -95,15 +95,15 @@ int main(void) { xTaskCreate(midi_task, "midi", MIDI_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL); #endif -#if !TUSB_MCU_VENDOR_ESPRESSIF - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 +#ifndef ESP_PLATFORM + // only start scheduler for non-espressif mcu vTaskStartScheduler(); #endif return 0; } -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM void app_main(void) { main(); } diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c index 04d4af4e5..0406279fd 100644 --- a/examples/device/video_capture/src/main.c +++ b/examples/device/video_capture/src/main.c @@ -292,7 +292,7 @@ void led_blinking_task(void* param) { #define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE #define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4) -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define USBD_STACK_SIZE 4096 int main(void); void app_main(void) { @@ -351,8 +351,8 @@ void freertos_init_task(void) { xTaskCreate(video_task, "video", VIDEO_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL); #endif - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 - #if !TUSB_MCU_VENDOR_ESPRESSIF + // only start scheduler for non-espressif mcu + #ifndef ESP_PLATFORM vTaskStartScheduler(); #endif } diff --git a/examples/device/video_capture/src/tusb_config.h b/examples/device/video_capture/src/tusb_config.h index 6dbd6f2a5..4ba86ca65 100644 --- a/examples/device/video_capture/src/tusb_config.h +++ b/examples/device/video_capture/src/tusb_config.h @@ -58,7 +58,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/device/video_capture_2ch/src/main.c b/examples/device/video_capture_2ch/src/main.c index 245e7abb8..dc616e3fa 100644 --- a/examples/device/video_capture_2ch/src/main.c +++ b/examples/device/video_capture_2ch/src/main.c @@ -300,7 +300,7 @@ void led_blinking_task(void* param) { #define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE #define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4) -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define USBD_STACK_SIZE 4096 int main(void); void app_main(void) { @@ -359,8 +359,8 @@ void freertos_init_task(void) { xTaskCreate(video_task, "video", VIDEO_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL); #endif - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 - #if !TUSB_MCU_VENDOR_ESPRESSIF + // only start scheduler for non-espressif mcu + #ifndef ESP_PLATFORM vTaskStartScheduler(); #endif } diff --git a/examples/device/video_capture_2ch/src/tusb_config.h b/examples/device/video_capture_2ch/src/tusb_config.h index 91775a327..e84e49879 100644 --- a/examples/device/video_capture_2ch/src/tusb_config.h +++ b/examples/device/video_capture_2ch/src/tusb_config.h @@ -58,7 +58,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c index e279ad509..d99760a02 100644 --- a/examples/host/cdc_msc_hid_freertos/src/cdc_app.c +++ b/examples/host/cdc_msc_hid_freertos/src/cdc_app.c @@ -27,7 +27,7 @@ #include "tusb.h" #include "bsp/board_api.h" -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define CDC_STACK_SZIE 2048 #else #define CDC_STACK_SZIE (3*configMINIMAL_STACK_SIZE/2) diff --git a/examples/host/cdc_msc_hid_freertos/src/main.c b/examples/host/cdc_msc_hid_freertos/src/main.c index 64a108254..0bcb355ec 100644 --- a/examples/host/cdc_msc_hid_freertos/src/main.c +++ b/examples/host/cdc_msc_hid_freertos/src/main.c @@ -30,7 +30,7 @@ #include "bsp/board_api.h" #include "tusb.h" -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define USBH_STACK_SIZE 4096 #else // Increase stack size when debug log is enabled @@ -86,15 +86,15 @@ int main(void) { xTimerStart(blinky_tm, 0); - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 -#if !TUSB_MCU_VENDOR_ESPRESSIF + // only start scheduler for non-espressif mcu +#ifndef ESP_PLATFORM vTaskStartScheduler(); #endif return 0; } -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM void app_main(void) { main(); } diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index bc8887211..3cdb227e2 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -44,7 +44,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c index e924a137b..7189972d6 100644 --- a/examples/host/device_info/src/main.c +++ b/examples/host/device_info/src/main.c @@ -268,7 +268,7 @@ void led_blinking_task(void* param) { #define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define USB_STACK_SIZE 4096 #else // Increase stack size when debug log is enabled @@ -285,7 +285,7 @@ StackType_t usb_stack[USB_STACK_SIZE]; StaticTask_t usb_taskdef; #endif -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM void app_main(void) { main(); } @@ -308,8 +308,8 @@ void init_freertos_task(void) { xTaskCreate(usb_host_task, "usbh", USB_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); #endif - // skip starting scheduler (and return) for ESP32-S2 or ESP32-S3 -#if !TUSB_MCU_VENDOR_ESPRESSIF + // only start scheduler for non-espressif mcu +#ifndef ESP_PLATFORM vTaskStartScheduler(); #endif } diff --git a/examples/host/device_info/src/tusb_config.h b/examples/host/device_info/src/tusb_config.h index e12970c12..e4ca2528e 100644 --- a/examples/host/device_info/src/tusb_config.h +++ b/examples/host/device_info/src/tusb_config.h @@ -40,7 +40,7 @@ #endif // Espressif IDF requires "freertos/" prefix in include path -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/host/midi_rx/src/tusb_config.h b/examples/host/midi_rx/src/tusb_config.h index c9b430388..76bdf87f3 100644 --- a/examples/host/midi_rx/src/tusb_config.h +++ b/examples/host/midi_rx/src/tusb_config.h @@ -40,7 +40,7 @@ extern "C" { #endif // Espressif IDF requires "freertos/" prefix in include path -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM #define CFG_TUSB_OS_INC_PATH freertos/ #endif diff --git a/examples/typec/power_delivery/src/main.c b/examples/typec/power_delivery/src/main.c index 068dbbeb1..de0db4721 100644 --- a/examples/typec/power_delivery/src/main.c +++ b/examples/typec/power_delivery/src/main.c @@ -71,9 +71,8 @@ int main(void) } } -#if TUSB_MCU_VENDOR_ESPRESSIF -void app_main(void) -{ +#ifdef ESP_PLATFORM +void app_main(void) { main(); } #endif diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 4b8e5950f..8f2f93306 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -66,7 +66,6 @@ int sys_read(int fhdl, char *buf, size_t count) { #elif defined(LOGGER_SWO) #define ITM_BASE 0xE0000000 - #define ITM_STIM0 (*((volatile uint8_t*)(ITM_BASE + 0))) #define ITM_TER *((volatile uint32_t*)(ITM_BASE + 0xE00)) #define ITM_TCR *((volatile uint32_t*)(ITM_BASE + 0xE80)) @@ -150,6 +149,9 @@ int board_getchar(void) { return (sys_read(0, &c, 1) > 0) ? (int) c : (-1); } +void board_putchar(int c) { + sys_write(0, (const char*)&c, 1); +} uint32_t tusb_time_millis_api(void) { return board_millis(); @@ -158,7 +160,7 @@ uint32_t tusb_time_millis_api(void) { //-------------------------------------------------------------------- // FreeRTOS hooks //-------------------------------------------------------------------- -#if CFG_TUSB_OS == OPT_OS_FREERTOS && !TUSB_MCU_VENDOR_ESPRESSIF +#if CFG_TUSB_OS == OPT_OS_FREERTOS && !defined(ESP_PLATFORM) #include "FreeRTOS.h" #include "task.h" @@ -240,5 +242,4 @@ void vApplicationSetupTimerInterrupt(void) { } #endif - #endif diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 9cdbbf0d3..328fe9363 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -41,7 +41,7 @@ extern "C" { #if CFG_TUSB_OS == OPT_OS_ZEPHYR #include #elif CFG_TUSB_OS == OPT_OS_FREERTOS - #if TUSB_MCU_VENDOR_ESPRESSIF + #ifdef ESP_PLATFORM // ESP-IDF need "freertos/" prefix in include path. // CFG_TUSB_OS_INC_PATH should be defined accordingly. #include "freertos/FreeRTOS.h" @@ -195,6 +195,7 @@ static inline void board_delay(uint32_t ms) { // stdio getchar() is blocking, this is non-blocking version int board_getchar(void); +void board_putchar(int c); #ifdef __cplusplus } diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index 8f6c4bee2..2a5deed26 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -156,6 +156,10 @@ int board_getchar(void) { return getchar(); } +void board_putchar(int c) { + putchar(c); +} + //-------------------------------------------------------------------- // PHY Init //-------------------------------------------------------------------- diff --git a/tools/build.py b/tools/build.py index 6e73681fe..eaa383d73 100755 --- a/tools/build.py +++ b/tools/build.py @@ -101,10 +101,8 @@ def cmake_board(board, toolchain, build_flags_on): if build_utils.skip_example(example, board): ret[2] += 1 else: - rcmd = run_cmd(f'cmake examples/{example} -B {build_dir}/{example} -G Ninja ' - f'-DBOARD={board} {build_flags}') - if rcmd.returncode == 0: - rcmd = run_cmd(f'cmake --build {build_dir}/{example}') + rcmd = run_cmd(f'idf.py -C examples/{example} -B {build_dir}/{example} -G Ninja ' + f'-DBOARD={board} {build_flags} build') ret[0 if rcmd.returncode == 0 else 1] += 1 else: rcmd = run_cmd(f'cmake examples -B {build_dir} -G Ninja -DBOARD={board} -DCMAKE_BUILD_TYPE=MinSizeRel ' diff --git a/tools/build_utils.py b/tools/build_utils.py index 2998f940d..d80ceea7c 100755 --- a/tools/build_utils.py +++ b/tools/build_utils.py @@ -26,6 +26,8 @@ def skip_example(example, board): # family.mk family_mk = family_dir / "family.mk" + if not family_mk.exists(): + family_mk = family_dir / "family.cmake" mk_contents = family_mk.read_text() # Find the mcu, first in family mk then board mk From a8b5e2bfc0a2d35ba775f7b2de81d531ed525e41 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Jul 2025 15:38:14 +0700 Subject: [PATCH 252/382] update example --- examples/device/board_test/src/main.c | 21 ++++++++++++--------- examples/host/cdc_msc_hid/src/cdc_app.c | 5 ++++- hw/bsp/rp2040/family.c | 6 +++++- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c index 2269d45f1..2c6ab6288 100644 --- a/examples/device/board_test/src/main.c +++ b/examples/device/board_test/src/main.c @@ -49,25 +49,28 @@ int main(void) { while (1) { uint32_t interval_ms = board_button_read() ? BLINK_PRESSED : BLINK_UNPRESSED; + int ch = board_getchar(); + if (ch > 0) { + board_putchar(ch); + } + // Blink and print every interval ms if (!(board_millis() - start_ms < interval_ms)) { - board_uart_write(HELLO_STR, strlen(HELLO_STR)); - start_ms = board_millis(); + if (ch < 0) { + // skip if echoing + printf(HELLO_STR); + board_uart_write(HELLO_STR, strlen(HELLO_STR)); + } + board_led_write(led_state); led_state = 1 - led_state; // toggle } - - // echo - uint8_t ch; - if (board_uart_read(&ch, 1) > 0) { - board_uart_write(&ch, 1); - } } } -#if TUSB_MCU_VENDOR_ESPRESSIF +#ifdef ESP_PLATFORM void app_main(void) { main(); } diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index 2fa9a8560..97f1a96d6 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -72,7 +72,10 @@ void tuh_cdc_rx_cb(uint8_t idx) { if (count) { buf[count] = 0; printf("%s", (char*) buf); - fflush(stdout); + + #ifndef __ICCARM__ // TODO IAR doesn't support stream control ? + fflush(stdout);// flush right away, else nanolib will wait for newline + #endif } } diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c index 8c85c5cc8..a22924131 100644 --- a/hw/bsp/rp2040/family.c +++ b/hw/bsp/rp2040/family.c @@ -254,7 +254,7 @@ size_t board_get_unique_id(uint8_t id[], size_t max_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++; } @@ -282,6 +282,10 @@ int board_getchar(void) { return getchar_timeout_us(0); } +void board_putchar(int c) { + stdio_putchar(c); +} + //--------------------------------------------------------------------+ // USB Interrupt Handler // rp2040 implementation will install appropriate handler when initializing From 014d6b2f2647b5135e22d219b61b727cb9a20ae6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Jul 2025 15:55:42 +0700 Subject: [PATCH 253/382] remove cmake arm-clang and make iar to reduce concurrent jobs --- .github/workflows/build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 97f219e6f..5e11f8a29 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,7 +70,7 @@ jobs: matrix: toolchain: - 'aarch64-gcc' - - 'arm-clang' + #- 'arm-clang' - 'arm-gcc' - 'esp-idf' - 'msp430-gcc' @@ -110,7 +110,8 @@ jobs: # cmake is built by circle-ci. Due to IAR limit capacity, only build oe per family # --------------------------------------- arm-iar: - if: github.event_name == 'push' && github.repository_owner == 'hathach' + if: false # disable for now since we got reach capacity limit too often + #if: github.event_name == 'push' && github.repository_owner == 'hathach' needs: set-matrix uses: ./.github/workflows/build_util.yml secrets: inherit From 52f0427096a9e20b62dc3055a153a60e50317297 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Jul 2025 16:34:17 +0700 Subject: [PATCH 254/382] remove make wrapper for rp2040/espressif --- docs/reference/getting_started.rst | 2 +- hw/bsp/rp2040/family.mk | 16 ---------------- tools/build.py | 21 +++++++++++++-------- 3 files changed, 14 insertions(+), 25 deletions(-) delete mode 100644 hw/bsp/rp2040/family.mk diff --git a/docs/reference/getting_started.rst b/docs/reference/getting_started.rst index ee68f6386..5b009f21e 100644 --- a/docs/reference/getting_started.rst +++ b/docs/reference/getting_started.rst @@ -82,7 +82,7 @@ You only need to do this once per family. Check out `complete list of dependenci Build Examples ^^^^^^^^^^^^^^ -Examples support make and cmake build system, though some MCU family such as espressif/rp2040 only support cmake. First change directory to an example folder. +Examples support make and cmake build system for most MCUs, however some MCU families such as espressif or rp2040 only support cmake. First change directory to an example folder. .. code-block:: bash diff --git a/hw/bsp/rp2040/family.mk b/hw/bsp/rp2040/family.mk deleted file mode 100644 index 813683c54..000000000 --- a/hw/bsp/rp2040/family.mk +++ /dev/null @@ -1,16 +0,0 @@ -JLINK_DEVICE = rp2040_m0_0 -PYOCD_TARGET = rp2040 - -ifeq ($(DEBUG), 1) -CMAKE_DEFSYM += -DCMAKE_BUILD_TYPE=Debug -endif - -$(BUILD): - cmake -S . -B $(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) -DPICO_BUILD_DOCS=0 $(CMAKE_DEFSYM) - -all: $(BUILD) - $(MAKE) -C $(BUILD) - -flash: flash-pyocd -flash-uf2: - @$(CP) $(BUILD)/$(PROJECT).uf2 /media/$(USER)/RPI-RP2 diff --git a/tools/build.py b/tools/build.py index eaa383d73..f639fba81 100755 --- a/tools/build.py +++ b/tools/build.py @@ -154,16 +154,21 @@ def make_one_example(example, board, make_option): def make_board(board, toolchain): print(build_separator) - all_examples = get_examples(find_family(board)) + family = find_family(board); + all_examples = get_examples(family) start_time = time.monotonic() ret = [0, 0, 0] - with Pool(processes=os.cpu_count()) as pool: - pool_args = list((map(lambda e, b=board, o=f"TOOLCHAIN={toolchain}": [e, b, o], all_examples))) - r = pool.starmap(make_one_example, pool_args) - # sum all element of same index (column sum) - ret = list(map(sum, list(zip(*r)))) - example = 'all' - print_build_result(board, example, 0 if ret[1] == 0 else 1, time.monotonic() - start_time) + if family == 'espressif' or family == 'rp2040': + # espressif and rp2040 do not support make, use cmake instead + final_status = 2 + else: + with Pool(processes=os.cpu_count()) as pool: + pool_args = list((map(lambda e, b=board, o=f"TOOLCHAIN={toolchain}": [e, b, o], all_examples))) + r = pool.starmap(make_one_example, pool_args) + # sum all element of same index (column sum) + ret = list(map(sum, list(zip(*r)))) + final_status = 0 if ret[1] == 0 else 1 + print_build_result(board, 'all', final_status, time.monotonic() - start_time) return ret From a64e3eb0aa661db14eb647e2f75059815741112f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Jul 2025 17:27:03 +0700 Subject: [PATCH 255/382] update board_test always output to uart regardless of LOGGER option --- docs/reference/getting_started.rst | 4 ++-- examples/build_system/make/make.mk | 19 ++++++++----------- examples/device/board_test/src/main.c | 6 ++++++ hw/bsp/board.c | 1 - hw/bsp/family_support.cmake | 2 ++ test/fuzz/make.mk | 6 ------ 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/docs/reference/getting_started.rst b/docs/reference/getting_started.rst index 5b009f21e..bb9ff1cb4 100644 --- a/docs/reference/getting_started.rst +++ b/docs/reference/getting_started.rst @@ -256,8 +256,8 @@ Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\ 2. Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\examples\\(.ipcf of example)``. For example ``C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf`` -Native CMake support (9.50.1+) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Native CMake support +~~~~~~~~~~~~~~~~~~~~ With 9.50.1 release, IAR added experimental native CMake support (strangely not mentioned in public release note). Now it's possible to import CMakeLists.txt then build and debug as a normal project. diff --git a/examples/build_system/make/make.mk b/examples/build_system/make/make.mk index dbc73903e..f70748d34 100644 --- a/examples/build_system/make/make.mk +++ b/examples/build_system/make/make.mk @@ -123,27 +123,24 @@ endif ifeq (${MAX3421_HOST},1) SRC_C += src/portable/analog/max3421/hcd_max3421.c CFLAGS += -DCFG_TUH_MAX3421=1 - CMAKE_DEFSYM += -DMAX3421_HOST=1 endif # Log level is mapped to TUSB DEBUG option ifneq ($(LOG),) - CMAKE_DEFSYM += -DLOG=$(LOG) CFLAGS += -DCFG_TUSB_DEBUG=$(LOG) endif # Logger: default is uart, can be set to rtt or swo -ifneq ($(LOGGER),) - CMAKE_DEFSYM += -DLOGGER=$(LOGGER) -endif - ifeq ($(LOGGER),rtt) - CFLAGS += -DLOGGER_RTT -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL - RTT_SRC = lib/SEGGER_RTT - INC += $(TOP)/$(RTT_SRC)/RTT - SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT.c -else ifeq ($(LOGGER),swo) + CFLAGS += -DLOGGER_RTT + #CFLAGS += -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL + INC += $(TOP)/$(lib/SEGGER_RTT)/RTT + SRC_C += $(lib/SEGGER_RTT)/RTT/SEGGER_RTT.c +endif +ifeq ($(LOGGER),swo) CFLAGS += -DLOGGER_SWO +else + CFLAGS += -DLOGGER_UART endif # CPU specific flags diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c index 2c6ab6288..d91a8760e 100644 --- a/examples/device/board_test/src/main.c +++ b/examples/device/board_test/src/main.c @@ -52,6 +52,9 @@ int main(void) { int ch = board_getchar(); if (ch > 0) { board_putchar(ch); + #ifndef LOGGER_UART + board_uart_write(&ch, 1); + #endif } // Blink and print every interval ms @@ -61,7 +64,10 @@ int main(void) { if (ch < 0) { // skip if echoing printf(HELLO_STR); + + #ifndef LOGGER_UART board_uart_write(HELLO_STR, strlen(HELLO_STR)); + #endif } board_led_write(led_state); diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 8f2f93306..1ba5a1b9d 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -60,7 +60,6 @@ int sys_read(int fhdl, char *buf, size_t count) { int rd = (int) SEGGER_RTT_Read(0, buf, count); return (rd > 0) ? rd : -1; } - #endif #elif defined(LOGGER_SWO) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 0509fdc28..9ec80df91 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -221,6 +221,8 @@ function(family_configure_common TARGET RTOS) target_include_directories(${TARGET} PUBLIC ${TOP}/lib/SEGGER_RTT/RTT) # target_compile_definitions(${TARGET} PUBLIC SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) endif () + else () + target_compile_definitions(${TARGET} PUBLIC LOGGER_UART) endif () if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") diff --git a/test/fuzz/make.mk b/test/fuzz/make.mk index b7b6d6a75..e9aa80bf1 100644 --- a/test/fuzz/make.mk +++ b/test/fuzz/make.mk @@ -124,11 +124,5 @@ endif # Log level is mapped to TUSB DEBUG option ifneq ($(LOG),) - CMAKE_DEFSYM += -DLOG=$(LOG) CFLAGS += -DCFG_TUSB_DEBUG=$(LOG) endif - -# Logger: default is uart, can be set to rtt or swo -ifneq ($(LOGGER),) - CMAKE_DEFSYM += -DLOGGER=$(LOGGER) -endif From a52e5ce99aa4fba305e5b8639360d5b3990d7475 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 2 Jul 2025 17:43:38 +0700 Subject: [PATCH 256/382] build iar with circleci large resource --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3b4389ab4..c2f6c4356 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -66,7 +66,7 @@ jobs: FAMILY_LARGE=$(jq -n --argjson family "$FAMILY" --argjson resource "$RESOURCE_LARGE" '$family | map(select(IN($resource[])))') FAMILY=$(jq -n --argjson family "$FAMILY" --argjson resource "$RESOURCE_LARGE" '$family | map(select(IN($resource[]) | not))') - if [[ $toolchain == esp-idf ]]; then + if [[ $toolchain == esp-idf || $toolchain == arm-iar ]]; then gen_build_entry "$build_system" "$toolchain" "$FAMILY" "large" else gen_build_entry "$build_system" "$toolchain" "$FAMILY" "medium+" From 41606a533dbe4bb7e031267d2869401243d2a0aa Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Jul 2025 13:42:05 +0700 Subject: [PATCH 257/382] make notify API and memory configurable with CFG_TUD_CDC_NOTIFY add tud_cdc_n_notify_conn_speed_change() add tud_cdc_notify_complete_cb() --- examples/device/cdc_dual_ports/src/main.c | 13 +-- .../device/cdc_dual_ports/src/tusb_config.h | 2 + .../cdc_dual_ports/src/usb_descriptors.c | 47 ++++----- src/class/cdc/cdc.h | 95 ++++++++++--------- src/class/cdc/cdc_device.c | 79 ++++++++------- src/class/cdc/cdc_device.h | 34 +++++-- 6 files changed, 149 insertions(+), 121 deletions(-) diff --git a/examples/device/cdc_dual_ports/src/main.c b/examples/device/cdc_dual_ports/src/main.c index e5432eb23..5a3e18358 100644 --- a/examples/device/cdc_dual_ports/src/main.c +++ b/examples/device/cdc_dual_ports/src/main.c @@ -102,16 +102,13 @@ void tud_umount_cb(void) { // USB CDC //--------------------------------------------------------------------+ static void cdc_task(void) { - uint8_t itf; - - for (itf = 0; itf < CFG_TUD_CDC; itf++) { + for (uint8_t itf = 0; itf < CFG_TUD_CDC; itf++) { // connected() check for DTR bit // Most but not all terminal client set this when making connection // if ( tud_cdc_n_connected(itf) ) { if (tud_cdc_n_available(itf)) { uint8_t buf[64]; - uint32_t count = tud_cdc_n_read(itf, buf, sizeof(buf)); // echo back to both serial ports @@ -121,11 +118,11 @@ static void cdc_task(void) { // Press on-board button to send Uart status notification static uint32_t btn_prev = 0; - static cdc_uart_state_t state = {0}; - uint32_t btn = board_button_read(); + static cdc_notify_uart_state_t uart_state = { .value = 0 }; + const uint32_t btn = board_button_read(); if (!btn_prev && btn) { - state.bTxCarrier ^= 1; - tud_cdc_send_uart_state(state); + uart_state.dsr ^= 1; + tud_cdc_notify_uart_state(&uart_state); } btn_prev = btn; } diff --git a/examples/device/cdc_dual_ports/src/tusb_config.h b/examples/device/cdc_dual_ports/src/tusb_config.h index 070f08ed1..7f7df3909 100644 --- a/examples/device/cdc_dual_ports/src/tusb_config.h +++ b/examples/device/cdc_dual_ports/src/tusb_config.h @@ -97,6 +97,8 @@ #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 +#define CFG_TUD_CDC_NOTIFY 1 // Enable use of notification endpoint + // CDC FIFO size of TX and RX #define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index 68eedd964..87309abbb 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -130,36 +130,32 @@ enum #define EPNUM_CDC_1_IN 0x84 #endif -uint8_t const desc_fs_configuration[] = -{ +uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 10, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 16, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 10, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 16, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64), }; #if TUD_OPT_HIGH_SPEED // Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration - -uint8_t const desc_hs_configuration[] = -{ +uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 10, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 16, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512), // 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 10, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 16, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512), }; // device qualifier is mostly similar to device descriptor since we don't change configuration based on speed -tusb_desc_device_qualifier_t const desc_device_qualifier = -{ +tusb_desc_device_qualifier_t const desc_device_qualifier = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -177,34 +173,31 @@ tusb_desc_device_qualifier_t const desc_device_qualifier = // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. // device_qualifier descriptor describes information about a high-speed capable device that would // change if the device were operating at the other speed. If not highspeed capable stall this request. -uint8_t const* tud_descriptor_device_qualifier_cb(void) -{ - return (uint8_t const*) &desc_device_qualifier; +uint8_t const *tud_descriptor_device_qualifier_cb(void) { + return (uint8_t const *) &desc_device_qualifier; } // Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete // Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa -uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) -{ - (void) index; // for multiple configurations +uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { + (void) index;// for multiple configurations // if link speed is high return fullspeed config, and vice versa - return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration; + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration; } -#endif // highspeed +#endif// highspeed // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ - (void) index; // for multiple configurations +uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { + (void) index;// for multiple configurations #if TUD_OPT_HIGH_SPEED // Although we are highspeed, host may be fullspeed. - return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; #else return desc_fs_configuration; #endif @@ -223,8 +216,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = -{ +char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product @@ -254,14 +246,14 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // 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]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if ( chr_count > max_count ) { chr_count = max_count; } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { @@ -272,6 +264,5 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // first byte is length (including header), second byte is string type _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); - return _desc_str; } diff --git a/src/class/cdc/cdc.h b/src/class/cdc/cdc.h index a403d77fa..10ba16a7c 100644 --- a/src/class/cdc/cdc.h +++ b/src/class/cdc/cdc.h @@ -221,18 +221,20 @@ typedef enum { // Management Element Notification (Notification Endpoint) //--------------------------------------------------------------------+ +#define CDC_REQ_TYPE_NOTIF 0xA1 ///< Direction IN; Type Class; Recipient Interface + /// 6.3 Notification Codes typedef enum { - CDC_NOTIF_NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status. - CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request. + CDC_NOTIF_NETWORK_CONNECTION = 0x00, // notify the host about network connection status. + CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, // notify the host that a response is available. CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08, CDC_NOTIF_RING_DETECT = 0x09, CDC_NOTIF_SERIAL_STATE = 0x20, CDC_NOTIF_CALL_STATE_CHANGE = 0x28, CDC_NOTIF_LINE_STATE_CHANGE = 0x29, - CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, ///< This notification allows the device to inform the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred + CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, // notify the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred CDC_NOTIF_MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40, -}cdc_notification_request_t; +} cdc_notify_request_t; //--------------------------------------------------------------------+ // Class Specific Functional Descriptor (Communication Interface) @@ -243,8 +245,7 @@ TU_ATTR_PACKED_BEGIN TU_ATTR_BIT_FIELD_ORDER_BEGIN /// Header Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_ @@ -252,8 +253,7 @@ typedef struct TU_ATTR_PACKED }cdc_desc_func_header_t; /// Union Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ @@ -271,14 +271,13 @@ typedef struct TU_ATTR_PACKED } /// Country Selection Functional Descriptor (Communication Interface) -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes. uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country. -}cdc_desc_func_country_selection_t; +} cdc_desc_func_country_selection_t; #define cdc_desc_func_country_selection_n_t(no_country) \ struct TU_ATTR_PACKED { \ @@ -295,8 +294,7 @@ typedef struct TU_ATTR_PACKED /// \brief Call Management Functional Descriptor /// \details This functional descriptor describes the processing of calls for the Communications Class interface. -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ @@ -310,8 +308,7 @@ typedef struct TU_ATTR_PACKED uint8_t bDataInterface; }cdc_desc_func_call_management_t; -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature. uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State. uint8_t support_send_break : 1; ///< Device supports the request Send_Break @@ -323,8 +320,7 @@ TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compile /// Abstract Control Management Functional Descriptor /// This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ @@ -333,8 +329,7 @@ typedef struct TU_ATTR_PACKED /// \brief Direct Line Management Functional Descriptor /// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_ @@ -396,8 +391,7 @@ typedef struct TU_ATTR_PACKED }cdc_desc_func_telephone_call_state_reporting_capabilities_t; // TODO remove -static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) { return p_desc[2]; } @@ -414,7 +408,7 @@ typedef struct TU_ATTR_PACKED { TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct"); typedef union TU_ATTR_PACKED { - struct { + struct TU_ATTR_PACKED { uint8_t dtr : 1; uint8_t rts : 1; uint8_t : 6; @@ -427,31 +421,44 @@ TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 1, "size is not correct"); //--------------------------------------------------------------------+ // Notifications //--------------------------------------------------------------------+ -typedef struct TU_ATTR_PACKED -{ - uint16_t bRxCarrier : 1; - uint16_t bTxCarrier : 1; - uint16_t bBreak : 1; - uint16_t bRingSignal : 1; - uint16_t bFraming : 1; - uint16_t bParity : 1; - uint16_t bOverRun : 1; - uint16_t : 9; -} cdc_uart_state_t; +// PSTN 1.2 section 6.5.4 table 31 +typedef union TU_ATTR_PACKED { + struct TU_ATTR_PACKED { + uint16_t bRxCarrier : 1; // DCD + uint16_t bTxCarrier : 1; // DSR + uint16_t bBreak : 1; // Break Detected + uint16_t bRingSignal : 1; + uint16_t bFraming : 1; + uint16_t bParity : 1; + uint16_t bOverRun : 1; + uint16_t : 9; + }; + struct TU_ATTR_PACKED { + uint16_t dcd : 1; + uint16_t dsr : 1; + uint16_t brk : 1; + uint16_t :13; + }; + uint16_t value; +} cdc_notify_uart_state_t; -typedef struct TU_ATTR_PACKED -{ - uint8_t bmRequestType; - uint8_t bNotification; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; - cdc_uart_state_t bmUartState; -} cdc_notif_serial_state_t; +TU_VERIFY_STATIC(sizeof(cdc_notify_uart_state_t) == 2, "size is not correct"); -TU_VERIFY_STATIC(sizeof(cdc_notif_serial_state_t) == 10, "size is not correct"); +// CDC 1.2 section 6.3.3 table 21 +typedef struct TU_ATTR_PACKED { + uint32_t upstream_bitrate; + uint32_t downstream_bitrate; +} cdc_notify_conn_speed_change_t; -#define CDC_REQ_TYPE_NOTIF 0xA1 ///< Direction IN; Type Class; Recipient Interface +typedef struct TU_ATTR_PACKED { + tusb_control_request_t request; + union { + cdc_notify_uart_state_t serial_state; + cdc_notify_conn_speed_change_t conn_speed_change; + }; +} cdc_notify_msg_t; + +TU_VERIFY_STATIC(sizeof(cdc_notify_msg_t) == 16, "size is not correct"); TU_ATTR_PACKED_END // End of all packed definitions TU_ATTR_BIT_FIELD_ORDER_END diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 786c3aa55..4e4e01eaf 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -48,12 +48,11 @@ typedef struct { uint8_t rhport; uint8_t itf_num; - uint8_t ep_notif; uint8_t ep_in; uint8_t ep_out; - // Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send) - uint8_t line_state; + uint8_t ep_notify; + uint8_t line_state; // Bit 0: DTR, Bit 1: RTS /*------------- From this point, data is not cleared by bus reset -------------*/ char wanted_char; @@ -75,7 +74,10 @@ typedef struct { typedef struct { TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE); TUD_EPBUF_DEF(epin, CFG_TUD_CDC_EP_BUFSIZE); - TUD_EPBUF_TYPE_DEF(cdc_notif_serial_state_t, epnotif); + + #if CFG_TUD_CDC_NOTIFY + TUD_EPBUF_TYPE_DEF(cdc_notify_msg_t, epnotify); + #endif } cdcd_epbuf_t; //--------------------------------------------------------------------+ @@ -120,7 +122,6 @@ static bool _prep_out_transaction(uint8_t itf) { //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ - bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg) { TU_VERIFY(driver_cfg); _cdcd_cfg = *driver_cfg; @@ -144,27 +145,42 @@ void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding) { (*coding) = _cdcd_itf[itf].line_coding; } -bool tud_cdc_n_send_uart_state (uint8_t itf, cdc_uart_state_t state) { +#if CFG_TUD_CDC_NOTIFY +bool tud_cdc_n_notify_uart_state (uint8_t itf, const cdc_notify_uart_state_t *state) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; + TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0); + TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify)); - // Skip if usb is not ready yet - TU_VERIFY(tud_ready(), 0); + cdc_notify_msg_t* notify_msg = &p_epbuf->epnotify; + notify_msg->request.bmRequestType = CDC_REQ_TYPE_NOTIF; + notify_msg->request.bRequest = CDC_NOTIF_SERIAL_STATE; + notify_msg->request.wValue = 0; + notify_msg->request.wIndex = p_cdc->itf_num; + notify_msg->request.wLength = sizeof(cdc_notify_uart_state_t); + notify_msg->serial_state = *state; - // claim endpoint - TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notif)); - - p_epbuf->epnotif.bmRequestType = CDC_REQ_TYPE_NOTIF; - p_epbuf->epnotif.bNotification = CDC_NOTIF_SERIAL_STATE; - p_epbuf->epnotif.wValue = 0; - p_epbuf->epnotif.wIndex = p_cdc->itf_num; - p_epbuf->epnotif.wLength = 2; - p_epbuf->epnotif.bmUartState = state; - - // transfer - return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notif, (uint8_t *)&p_epbuf->epnotif, sizeof(cdc_notif_serial_state_t)); + return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_uart_state_t)); } +bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t* conn_speed_change) { + cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; + cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; + TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0); + TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify)); + + cdc_notify_msg_t* notify_msg = &p_epbuf->epnotify; + notify_msg->request.bmRequestType = CDC_REQ_TYPE_NOTIF; + notify_msg->request.bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE; + notify_msg->request.wValue = 0; + notify_msg->request.wIndex = p_cdc->itf_num; + notify_msg->request.wLength = sizeof(cdc_notify_conn_speed_change_t); + notify_msg->conn_speed_change = *conn_speed_change; + + return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_conn_speed_change_t)); +} +#endif + void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) { _cdcd_itf[itf].wanted_char = wanted; } @@ -215,25 +231,20 @@ uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) { uint32_t tud_cdc_n_write_flush(uint8_t itf) { cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; - - // Skip if usb is not ready yet - TU_VERIFY(tud_ready(), 0); + TU_VERIFY(tud_ready(), 0); // Skip if usb is not ready yet // No data to send if (!tu_fifo_count(&p_cdc->tx_ff)) { return 0; } - const uint8_t rhport = 0; - - // Claim the endpoint - TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_in), 0); + TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_in), 0); // Claim the endpoint // Pull data from FIFO const uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE); if (count) { - TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, p_epbuf->epin, count), 0); + TU_ASSERT(usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_in, p_epbuf->epin, count), 0); return count; } else { // Release endpoint since we don't make any transfer @@ -357,9 +368,8 @@ uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16 if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { // notification endpoint const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc; - TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); - p_cdc->ep_notif = desc_ep->bEndpointAddress; + p_cdc->ep_notify = desc_ep->bEndpointAddress; drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); @@ -479,7 +489,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ // Identify which interface to use for (itf = 0; itf < CFG_TUD_CDC; itf++) { p_cdc = &_cdcd_itf[itf]; - if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in) || (ep_addr == p_cdc->ep_notif)) { + if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in) || (ep_addr == p_cdc->ep_notify)) { break; } } @@ -528,7 +538,12 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } } - // nothing to do with notif endpoint for now + // Sent notification to host + if (ep_addr == p_cdc->ep_notify) { + if (tud_cdc_notify_complete_cb) { + tud_cdc_notify_complete_cb(itf); + } + } return true; } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index f6fa5abf8..a34e07e1d 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -32,6 +32,10 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ +#ifndef CFG_TUD_CDC_NOTIFY + #define CFG_TUD_CDC_NOTIFY 0 +#endif + #if !defined(CFG_TUD_CDC_EP_BUFSIZE) && defined(CFG_TUD_CDC_EPSIZE) #warning CFG_TUD_CDC_EPSIZE is renamed to CFG_TUD_CDC_EP_BUFSIZE, please update to use the new name #define CFG_TUD_CDC_EP_BUFSIZE CFG_TUD_CDC_EPSIZE @@ -83,9 +87,6 @@ uint8_t tud_cdc_n_get_line_state(uint8_t itf); // Get current line encoding: bit rate, stop bits parity etc .. void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding); -// Send UART status notification: DCD, DSR etc .. -bool tud_cdc_n_send_uart_state(uint8_t itf, cdc_uart_state_t state); - // Set special character that will trigger tud_cdc_rx_wanted_cb() callback on receiving void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted); @@ -129,6 +130,23 @@ uint32_t tud_cdc_n_write_available(uint8_t itf); // Clear the transmit FIFO bool tud_cdc_n_write_clear(uint8_t itf); + +#if CFG_TUD_CDC_NOTIFY +// Send UART status notification: DCD, DSR etc .. +bool tud_cdc_n_notify_uart_state(uint8_t itf, const cdc_notify_uart_state_t *state); + +// Send connection speed change notification +bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t* conn_speed_change); + +TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_notify_uart_state(const cdc_notify_uart_state_t* state) { + return tud_cdc_n_notify_uart_state(0, state); +} + +TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_notify_conn_speed_change(const cdc_notify_conn_speed_change_t* conn_speed_change) { + return tud_cdc_n_notify_conn_speed_change(0, conn_speed_change); +} +#endif + //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ @@ -149,11 +167,6 @@ TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_get_line_coding(cdc_line_coding tud_cdc_n_get_line_coding(0, coding); } -TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_send_uart_state(cdc_uart_state_t state) { - return tud_cdc_n_send_uart_state(0, state); -} - - TU_ATTR_ALWAYS_INLINE static inline void tud_cdc_set_wanted_char(char wanted) { tud_cdc_n_set_wanted_char(0, wanted); } @@ -203,7 +216,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_write_clear(void) { } //--------------------------------------------------------------------+ -// Application Callback API (weak is optional) +// Application Callback API //--------------------------------------------------------------------+ // Invoked when received new data @@ -215,6 +228,9 @@ TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char); // Invoked when a TX is complete and therefore space becomes available in TX buffer TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf); +// Invoked when a notification is sent to host +TU_ATTR_WEAK void tud_cdc_notify_complete_cb(uint8_t itf); + // Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts); From 0df3bfb81d33d11432824bbf91ab0eb260f6f14f Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Jul 2025 14:28:19 +0700 Subject: [PATCH 258/382] update cdc_msc/cdc_msc_freertos to also support notification --- .../cdc_dual_ports/src/usb_descriptors.c | 11 ++++----- examples/device/cdc_msc/src/main.c | 10 ++++++++ examples/device/cdc_msc/src/tusb_config.h | 4 +++- examples/device/cdc_msc/src/usb_descriptors.c | 11 ++++----- examples/device/cdc_msc_freertos/src/main.c | 10 ++++++++ .../device/cdc_msc_freertos/src/tusb_config.h | 2 ++ .../cdc_msc_freertos/src/usb_descriptors.c | 24 +++++++------------ 7 files changed, 42 insertions(+), 30 deletions(-) diff --git a/examples/device/cdc_dual_ports/src/usb_descriptors.c b/examples/device/cdc_dual_ports/src/usb_descriptors.c index 87309abbb..bbcb479f5 100644 --- a/examples/device/cdc_dual_ports/src/usb_descriptors.c +++ b/examples/device/cdc_dual_ports/src/usb_descriptors.c @@ -42,8 +42,7 @@ //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ +tusb_desc_device_t const desc_device = { .bLength = sizeof(tusb_desc_device_t), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = USB_BCD, @@ -68,16 +67,14 @@ tusb_desc_device_t const desc_device = // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ +uint8_t const *tud_descriptor_device_cb(void) { return (uint8_t const *) &desc_device; } //--------------------------------------------------------------------+ // Configuration Descriptor //--------------------------------------------------------------------+ -enum -{ +enum { ITF_NUM_CDC_0 = 0, ITF_NUM_CDC_0_DATA, ITF_NUM_CDC_1, @@ -193,7 +190,7 @@ uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { - (void) index;// for multiple configurations + (void) index; // for multiple configurations #if TUD_OPT_HIGH_SPEED // Although we are highspeed, host may be fullspeed. diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index f36c910d7..5cd93e7dd 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -119,6 +119,16 @@ void cdc_task(void) { tud_cdc_write(buf, count); tud_cdc_write_flush(); } + + // Press on-board button to send Uart status notification + static uint32_t btn_prev = 0; + static cdc_notify_uart_state_t uart_state = { .value = 0 }; + const uint32_t btn = board_button_read(); + if (!btn_prev && btn) { + uart_state.dsr ^= 1; + tud_cdc_notify_uart_state(&uart_state); + } + btn_prev = btn; } } diff --git a/examples/device/cdc_msc/src/tusb_config.h b/examples/device/cdc_msc/src/tusb_config.h index 03e0e649c..811d464e9 100644 --- a/examples/device/cdc_msc/src/tusb_config.h +++ b/examples/device/cdc_msc/src/tusb_config.h @@ -87,7 +87,7 @@ //-------------------------------------------------------------------- #ifndef CFG_TUD_ENDPOINT0_SIZE -#define CFG_TUD_ENDPOINT0_SIZE 64 +#define CFG_TUD_ENDPOINT0_SIZE 64 #endif //------------- CLASS -------------// @@ -97,6 +97,8 @@ #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 +#define CFG_TUD_CDC_NOTIFY 1 // Enable use of notification endpoint + // CDC FIFO size of TX and RX #define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) diff --git a/examples/device/cdc_msc/src/usb_descriptors.c b/examples/device/cdc_msc/src/usb_descriptors.c index 4b6b88041..edcee0462 100644 --- a/examples/device/cdc_msc/src/usb_descriptors.c +++ b/examples/device/cdc_msc/src/usb_descriptors.c @@ -52,7 +52,6 @@ tusb_desc_device_t const desc_device = { .bDeviceClass = TUSB_CLASS_MISC, .bDeviceSubClass = MISC_SUBCLASS_COMMON, .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = USB_VID, @@ -131,7 +130,7 @@ uint8_t const desc_fs_configuration[] = { TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), @@ -146,7 +145,7 @@ uint8_t const desc_hs_configuration[] = { TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), @@ -197,7 +196,6 @@ uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { #endif // highspeed - // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete @@ -256,14 +254,14 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // 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]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if ( chr_count > max_count ) { chr_count = max_count; } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { @@ -274,6 +272,5 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // first byte is length (including header), second byte is string type _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); - return _desc_str; } diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 6fe964153..09ccc9bf3 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -189,6 +189,16 @@ void cdc_task(void *params) { } tud_cdc_write_flush(); + + // Press on-board button to send Uart status notification + static uint32_t btn_prev = 0; + static cdc_notify_uart_state_t uart_state = { .value = 0 }; + const uint32_t btn = board_button_read(); + if (!btn_prev && btn) { + uart_state.dsr ^= 1; + tud_cdc_notify_uart_state(&uart_state); + } + btn_prev = btn; } // For ESP32-Sx this delay is essential to allow idle how to run and reset watchdog diff --git a/examples/device/cdc_msc_freertos/src/tusb_config.h b/examples/device/cdc_msc_freertos/src/tusb_config.h index 71a0e985a..9cc3a18d1 100644 --- a/examples/device/cdc_msc_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_freertos/src/tusb_config.h @@ -104,6 +104,8 @@ #define CFG_TUD_MIDI 0 #define CFG_TUD_VENDOR 0 +#define CFG_TUD_CDC_NOTIFY 1 // Enable use of notification endpoint + // CDC FIFO size of TX and RX #define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) diff --git a/examples/device/cdc_msc_freertos/src/usb_descriptors.c b/examples/device/cdc_msc_freertos/src/usb_descriptors.c index 405a57fe4..a55fa3675 100644 --- a/examples/device/cdc_msc_freertos/src/usb_descriptors.c +++ b/examples/device/cdc_msc_freertos/src/usb_descriptors.c @@ -52,7 +52,6 @@ tusb_desc_device_t const desc_device = { .bDeviceClass = TUSB_CLASS_MISC, .bDeviceSubClass = MISC_SUBCLASS_COMMON, .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = USB_VID, @@ -131,7 +130,7 @@ uint8_t const desc_fs_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), @@ -147,7 +146,7 @@ uint8_t const desc_hs_configuration[] = TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. - TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), @@ -176,16 +175,14 @@ tusb_desc_device_qualifier_t const desc_device_qualifier = // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete. // device_qualifier descriptor describes information about a high-speed capable device that would // change if the device were operating at the other speed. If not highspeed capable stall this request. -uint8_t const* tud_descriptor_device_qualifier_cb(void) -{ +uint8_t const* tud_descriptor_device_qualifier_cb(void) { return (uint8_t const*) &desc_device_qualifier; } // Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete // Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa -uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) -{ +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) { (void) index; // for multiple configurations // if link speed is high return fullspeed config, and vice versa @@ -204,13 +201,12 @@ uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) { (void) index; // for multiple configurations #if TUD_OPT_HIGH_SPEED // Although we are highspeed, host may be fullspeed. - return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; #else return desc_fs_configuration; #endif @@ -229,8 +225,7 @@ enum { }; // array of pointer to string descriptors -char const *string_desc_arr[] = -{ +char const *string_desc_arr[] = { (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product @@ -261,14 +256,14 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // 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]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if ( chr_count > max_count ) { chr_count = max_count; } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { @@ -279,6 +274,5 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // first byte is length (including header), second byte is string type _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); - return _desc_str; } From 89da5a724dbd692527ee1d25d5ae71226d1dae56 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Jul 2025 14:28:44 +0700 Subject: [PATCH 259/382] reduce bInterval for default CDC descriptor from 16ms to 1ms --- src/device/usbd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/device/usbd.h b/src/device/usbd.h index de6007fb3..e5a848809 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -244,7 +244,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ /* CDC Union */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ /* Endpoint Notification */\ - 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\ + 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\ /* CDC Data Interface */\ 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\ /* Endpoint Out */\ From 211c2e380fb5744bef484ad9b59b2579e91d30b4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 3 Jul 2025 18:03:19 +0700 Subject: [PATCH 260/382] fix build with clang --- hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld b/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld index 86acf9742..b33838180 100644 --- a/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld +++ b/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld @@ -35,16 +35,12 @@ /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = ORIGIN(DTCM) + LENGTH(DTCM); /* end of "DTCM" Ram type memory */ - _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ __FLASH_BEGIN = 0x08000000; __FLASH_SIZE = 0x00010000; - __RAM_BEGIN = 0x24000000; __RAM_SIZE = 0x4FC00; __RAM_NONCACHEABLEBUFFER_SIZE = 0x400; @@ -63,6 +59,9 @@ MEMORY FLASH (xrw) : ORIGIN = __FLASH_BEGIN, LENGTH = __FLASH_SIZE } +/* Highest address of the user mode stack */ +_estack = ORIGIN(DTCM) + LENGTH(DTCM); /* end of "DTCM" Ram type memory */ + /* Sections */ SECTIONS { @@ -100,14 +99,14 @@ SECTIONS . = ALIGN(4); } >FLASH - .ARM.extab (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + .ARM.extab : { . = ALIGN(4); *(.ARM.extab* .gnu.linkonce.armextab.*) . = ALIGN(4); } >FLASH - .ARM (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + .ARM : { . = ALIGN(4); __exidx_start = .; @@ -116,7 +115,7 @@ SECTIONS . = ALIGN(4); } >FLASH - .preinit_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + .preinit_array : { . = ALIGN(4); PROVIDE_HIDDEN (__preinit_array_start = .); @@ -125,7 +124,7 @@ SECTIONS . = ALIGN(4); } >FLASH - .init_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + .init_array : { . = ALIGN(4); PROVIDE_HIDDEN (__init_array_start = .); @@ -135,7 +134,7 @@ SECTIONS . = ALIGN(4); } >FLASH - .fini_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + .fini_array : { . = ALIGN(4); PROVIDE_HIDDEN (__fini_array_start = .); From ffab23cf0f9e5422f55311e0b9f95d05e68082a6 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 4 Jul 2025 12:10:56 +0200 Subject: [PATCH 261/382] Revise DCache with RTT section Signed-off-by: HiFiPhile --- hw/bsp/stm32f7/family.c | 1 - hw/bsp/stm32h7/family.c | 1 - hw/bsp/stm32h7rs/family.c | 149 +++++++++++++++++- hw/bsp/stm32h7rs/family.cmake | 3 +- hw/bsp/stm32h7rs/family.mk | 3 +- hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.icf | 2 +- hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld | 5 - 7 files changed, 152 insertions(+), 12 deletions(-) diff --git a/hw/bsp/stm32f7/family.c b/hw/bsp/stm32f7/family.c index b82ab7d51..bf2d28e42 100644 --- a/hw/bsp/stm32f7/family.c +++ b/hw/bsp/stm32f7/family.c @@ -79,7 +79,6 @@ void OTG_HS_IRQHandler(void) { void board_init(void) { SCB_EnableICache(); - SCB_EnableDCache(); HAL_Init(); diff --git a/hw/bsp/stm32h7/family.c b/hw/bsp/stm32h7/family.c index 23bfcb90e..382b878b7 100644 --- a/hw/bsp/stm32h7/family.c +++ b/hw/bsp/stm32h7/family.c @@ -99,7 +99,6 @@ static void trace_etm_init(void) { void board_init(void) { SCB_EnableICache(); - SCB_EnableDCache(); HAL_Init(); diff --git a/hw/bsp/stm32h7rs/family.c b/hw/bsp/stm32h7rs/family.c index b6b2d70e9..b506a02ab 100644 --- a/hw/bsp/stm32h7rs/family.c +++ b/hw/bsp/stm32h7rs/family.c @@ -123,12 +123,157 @@ void log_swo_init(void) #define log_swo_init() #endif +static void MPU_AdjustRegionAddressSize(uint32_t Address, uint32_t Size, MPU_Region_InitTypeDef* pInit); +static void MPU_Config(void) +{ + MPU_Region_InitTypeDef MPU_InitStruct = {0}; + uint32_t index = MPU_REGION_NUMBER0; + uint32_t address; + uint32_t size; + + /* Disable the MPU */ + HAL_MPU_Disable(); + + /* Initialize the background region */ + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = index; + MPU_InitStruct.BaseAddress = 0x0; + MPU_InitStruct.Size = MPU_REGION_SIZE_4GB; + MPU_InitStruct.SubRegionDisable = 0x87; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; + MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + HAL_MPU_ConfigRegion(&MPU_InitStruct); + index++; + + /* Initialize the non cacheable region */ +#if defined ( __ICCARM__ ) + /* get the region attribute form the icf file */ + extern uint32_t NONCACHEABLEBUFFER_start; + extern uint32_t NONCACHEABLEBUFFER_size; + + address = (uint32_t)&NONCACHEABLEBUFFER_start; + size = (uint32_t)&NONCACHEABLEBUFFER_size; + +#elif defined (__CC_ARM) || defined(__ARMCC_VERSION) + extern uint32_t Image$$RW_NONCACHEABLEBUFFER$$Base; + extern uint32_t Image$$RW_NONCACHEABLEBUFFER$$Length; + extern uint32_t Image$$RW_NONCACHEABLEBUFFER$$ZI$$Length; + + address = (uint32_t)&Image$$RW_NONCACHEABLEBUFFER$$Base; + size = (uint32_t)&Image$$RW_NONCACHEABLEBUFFER$$Length + (uint32_t)&Image$$RW_NONCACHEABLEBUFFER$$ZI$$Length; +#elif defined ( __GNUC__ ) + extern int __NONCACHEABLEBUFFER_BEGIN; + extern int __NONCACHEABLEBUFFER_END; + + address = (uint32_t)&__NONCACHEABLEBUFFER_BEGIN; + size = (uint32_t)&__NONCACHEABLEBUFFER_END - (uint32_t)&__NONCACHEABLEBUFFER_BEGIN; +#else +#error "Compiler toolchain is unsupported" +#endif + + if (size != 0) + { + /* Configure the MPU attributes as Normal Non Cacheable */ + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.Number = index; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.SubRegionDisable = 0x00; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_AdjustRegionAddressSize(address, size, &MPU_InitStruct); + HAL_MPU_ConfigRegion(&MPU_InitStruct); + index++; + } + + /* Initialize the region corresponding to the execution area + (external or internal flash or external or internal RAM + depending on scatter file definition) */ +#if defined ( __ICCARM__ ) + extern uint32_t __ICFEDIT_region_ROM_start__; + extern uint32_t __ICFEDIT_region_ROM_end__; + address = (uint32_t)&__ICFEDIT_region_ROM_start__; + size = (uint32_t)&__ICFEDIT_region_ROM_end__ - (uint32_t)&__ICFEDIT_region_ROM_start__ + 1; +#elif defined (__CC_ARM) || defined(__ARMCC_VERSION) + extern uint32_t Image$$ER_ROM$$Base; + extern uint32_t Image$$ER_ROM$$Limit; + address = (uint32_t)&Image$$ER_ROM$$Base; + size = (uint32_t)&Image$$ER_ROM$$Limit-(uint32_t)&Image$$ER_ROM$$Base; +#elif defined ( __GNUC__ ) + extern uint32_t __FLASH_BEGIN; + extern uint32_t __FLASH_SIZE; + address = (uint32_t)&__FLASH_BEGIN; + size = (uint32_t)&__FLASH_SIZE; +#else +#error "Compiler toolchain is unsupported" +#endif + + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = index; + MPU_InitStruct.SubRegionDisable = 0u; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + MPU_AdjustRegionAddressSize(address, size, &MPU_InitStruct); + HAL_MPU_ConfigRegion(&MPU_InitStruct); + index++; + + /* Reset unused MPU regions */ + for(; index < __MPU_REGIONCOUNT ; index++) + { + /* All unused regions disabled */ + MPU_InitStruct.Enable = MPU_REGION_DISABLE; + MPU_InitStruct.Number = index; + HAL_MPU_ConfigRegion(&MPU_InitStruct); + } + + /* Enable the MPU */ + HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); +} + +/** + * @brief This function adjusts the MPU region Address and Size within an MPU configuration. + * @param Address memory address + * @param Size memory size + * @param pInit pointer to an MPU initialization structure + * @retval None + */ +static void MPU_AdjustRegionAddressSize(uint32_t Address, uint32_t Size, MPU_Region_InitTypeDef* pInit) +{ + /* Compute the MPU region size */ + pInit->Size = ((31 - __CLZ(Size)) - 1); + if (Size > (1u << (pInit->Size + 1))) + { + pInit->Size++; + } + uint32_t Modulo = Address % (1 << (pInit->Size - 1)); + if (0 != Modulo) + { + /* Align address with MPU region size considering there is no need to increase the size */ + pInit->BaseAddress = Address - Modulo; + } + else + { + pInit->BaseAddress = Address; + } +} + void board_init(void) { + HAL_Init(); + + MPU_Config(); SCB_EnableICache(); SCB_EnableDCache(); - HAL_Init(); - HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY); // Implemented in board.h diff --git a/hw/bsp/stm32h7rs/family.cmake b/hw/bsp/stm32h7rs/family.cmake index e70d37777..6b7915c93 100644 --- a/hw/bsp/stm32h7rs/family.cmake +++ b/hw/bsp/stm32h7rs/family.cmake @@ -87,7 +87,8 @@ function(add_board_target BOARD_TARGET) BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} BOARD_TUH_RHPORT=${RHPORT_HOST} BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} - SEGGER_RTT_SECTION=\"dtcm_data\" + SEGGER_RTT_SECTION=\"noncacheable_buffer\" + BUFFER_SIZE_UP=0x300 ) update_board(${BOARD_TARGET}) diff --git a/hw/bsp/stm32h7rs/family.mk b/hw/bsp/stm32h7rs/family.mk index c60a5c00d..45d4da0cf 100644 --- a/hw/bsp/stm32h7rs/family.mk +++ b/hw/bsp/stm32h7rs/family.mk @@ -43,7 +43,8 @@ CFLAGS += \ -DBOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} \ -DBOARD_TUH_RHPORT=${RHPORT_HOST} \ -DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} \ - -DSEGGER_RTT_SECTION="dtcm_data" \ + -DSEGGER_RTT_SECTION="noncacheable_buffer" \ + -DBUFFER_SIZE_UP=0x300 \ # GCC Flags CFLAGS_GCC += \ diff --git a/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.icf b/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.icf index 8398fa07b..786be3560 100644 --- a/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.icf +++ b/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.icf @@ -51,5 +51,5 @@ place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; place in ROM_region { readonly }; place in RAM_region { readwrite }; -place in DTCM_region { block CSTACK, block HEAP, section dtcm_data }; +place in DTCM_region { block CSTACK, block HEAP }; place in NONCACHEABLE_region { section noncacheable_buffer }; diff --git a/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld b/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld index b33838180..a96e1f211 100644 --- a/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld +++ b/hw/bsp/stm32h7rs/linker/stm32h7s3xx_flash.ld @@ -196,11 +196,6 @@ SECTIONS . = ALIGN(8); } >DTCM - .dtcm_data : - { - *(dtcm_data) - } >DTCM - /* Remove information from the compiler libraries */ /DISCARD/ : { From 6e88895dbc2b09e60b971f1587d19d3a2487c2f8 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Jul 2025 11:26:48 +0700 Subject: [PATCH 262/382] always define CFG_TUH_WCH_USBIP_USBFS=1 for ch32v20x since only port1 support host mode reformat hcd usbfs add uart rx for ch32v20x bsp --- hw/bsp/ch32v20x/family.c | 91 +-- hw/bsp/ch32v20x/family.cmake | 28 +- src/common/tusb_mcu.h | 8 +- src/portable/wch/dcd_ch32_usbhs.c | 2 +- src/portable/wch/hcd_ch32_usbfs.c | 931 +++++++++++++----------------- 5 files changed, 483 insertions(+), 577 deletions(-) diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index 2c212a82b..510f82981 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -20,59 +20,56 @@ manufacturer: WCH #include "bsp/board_api.h" #include "board.h" -/* CH32v203 depending on variants can support 2 USB IPs: FSDEV and USBFS. +/* CH32v203 depending on variants can support 2 USB IPs: FSDEV (port0) and USBFS (port1). * By default, we use FSDEV, but you can explicitly select by define: * - CFG_TUD_WCH_USBIP_FSDEV * - CFG_TUD_WCH_USBIP_USBFS */ -// USBFS -__attribute__((interrupt)) __attribute__((used)) -void USBHD_IRQHandler(void) { - #if CFG_TUD_WCH_USBIP_USBFS +// Port0: USBD (fsdev) +__attribute__((interrupt)) __attribute__((used)) void USB_LP_CAN1_RX0_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_FSDEV tud_int_handler(0); #endif - #if defined(CFG_TUH_WCH_USBIP_USBFS) && CFG_TUH_WCH_USBIP_USBFS - tuh_int_handler(0); - #endif } -__attribute__((interrupt)) __attribute__((used)) -void USBHDWakeUp_IRQHandler(void) { +__attribute__((interrupt)) __attribute__((used)) void USB_HP_CAN1_TX_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_FSDEV + tud_int_handler(0); + #endif + +} + +__attribute__((interrupt)) __attribute__((used)) void USBWakeUp_IRQHandler(void) { + #if CFG_TUD_WCH_USBIP_FSDEV + tud_int_handler(0); + #endif +} + +// Port1: USBFS +__attribute__((interrupt)) __attribute__((used)) void USBHD_IRQHandler(void) { + #if CFG_TUD_ENABLED && CFG_TUD_WCH_USBIP_USBFS + tud_int_handler(1); + #endif + + #if CFG_TUH_ENABLED + tuh_int_handler(1); + #endif +} + +__attribute__((interrupt)) __attribute__((used)) void USBHDWakeUp_IRQHandler(void) { #if CFG_TUD_WCH_USBIP_USBFS tud_int_handler(0); #endif } -// USBD (fsdev) -__attribute__((interrupt)) __attribute__((used)) -void USB_LP_CAN1_RX0_IRQHandler(void) { - #if CFG_TUD_WCH_USBIP_FSDEV - tud_int_handler(0); - #endif -} - -__attribute__((interrupt)) __attribute__((used)) -void USB_HP_CAN1_TX_IRQHandler(void) { - #if CFG_TUD_WCH_USBIP_FSDEV - tud_int_handler(0); - #endif - -} - -__attribute__((interrupt)) __attribute__((used)) -void USBWakeUp_IRQHandler(void) { - #if CFG_TUD_WCH_USBIP_FSDEV - tud_int_handler(0); - #endif -} - - +//--------------------------------------------------------------------+ +// Board API +//--------------------------------------------------------------------+ #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -__attribute__((interrupt)) -void SysTick_Handler(void) { +__attribute__((interrupt)) void SysTick_Handler(void) { SysTick->SR = 0; system_ticks++; } @@ -111,7 +108,7 @@ void board_init(void) { #ifdef UART_DEV UART_CLOCK_EN(); GPIO_InitTypeDef usart_init = { - .GPIO_Pin = UART_TX_PIN, + .GPIO_Pin = UART_TX_PIN | UART_RX_PIN, .GPIO_Speed = GPIO_Speed_50MHz, .GPIO_Mode = GPIO_Mode_AF_PP, }; @@ -122,7 +119,7 @@ void board_init(void) { .USART_WordLength = USART_WordLength_8b, .USART_StopBits = USART_StopBits_1, .USART_Parity = USART_Parity_No, - .USART_Mode = USART_Mode_Tx, + .USART_Mode = USART_Mode_Tx | USART_Mode_Rx, .USART_HardwareFlowControl = USART_HardwareFlowControl_None, }; USART_Init(UART_DEV, &usart); @@ -192,9 +189,19 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) { } int board_uart_read(uint8_t *buf, int len) { - (void) buf; - (void) len; +#ifdef UART_DEV + int count; + for (count = 0; count < len; count++) { + if (USART_GetFlagStatus(UART_DEV, USART_FLAG_RXNE) == RESET) { + break; + } + buf[count] = USART_ReceiveData(UART_DEV); + } + return count; +#else + (void) buf; (void) len; return 0; +#endif } int board_uart_write(void const *buf, int len) { @@ -210,7 +217,3 @@ int board_uart_write(void const *buf, int len) { return len; } - -//-------------------------------------------------------------------- -// Neopixel -//-------------------------------------------------------------------- diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake index 6092abc8d..10044d5b3 100644 --- a/hw/bsp/ch32v20x/family.cmake +++ b/hw/bsp/ch32v20x/family.cmake @@ -16,9 +16,12 @@ set(FAMILY_MCUS CH32V20X CACHE INTERNAL "") set(OPENOCD_OPTION "-f ${CMAKE_CURRENT_LIST_DIR}/wch-riscv.cfg") # Port0 use FSDev, Port1 use USBFS -if (NOT DEFINED PORT) - set(PORT 0) -endif() +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 0) +endif () + +# only port1 support host mode +set(RHPORT_HOST 1) #------------------------------------ # BOARD_TARGET @@ -56,19 +59,16 @@ function(add_board_target BOARD_TARGET) ) target_compile_definitions(${BOARD_TARGET} PUBLIC CH32V20x_${MCU_VARIANT} + BOARD_TUD_RHPORT=${RHPORT_DEVICE} + BOARD_TUH_RHPORT=${RHPORT_HOST} ) - if (PORT EQUAL 0) - target_compile_definitions(${BOARD_TARGET} PUBLIC - CFG_TUD_WCH_USBIP_FSDEV=1 - CFG_TUH_WCH_USBIP_USBFS=1 - ) - elseif (PORT EQUAL 1) - target_compile_definitions(${BOARD_TARGET} PUBLIC - CFG_TUD_WCH_USBIP_USBFS=1 - ) + if (RHPORT_DEVICE EQUAL 0) + target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUD_WCH_USBIP_FSDEV=1) + elseif (RHPORT_DEVICE EQUAL 1) + target_compile_definitions(${BOARD_TARGET} PUBLIC CFG_TUH_WCH_USBIP_USBFS=1) else() - message(FATAL_ERROR "Invalid PORT ${PORT}") + message(FATAL_ERROR "Invalid RHPORT_DEVICE ${RHPORT_DEVICE}") endif() update_board(${BOARD_TARGET}) @@ -133,8 +133,6 @@ function(family_configure_example TARGET RTOS) ) target_link_libraries(${TARGET} PUBLIC board_${BOARD}) - - # Flashing family_add_bin_hex(${TARGET}) family_flash_openocd_wch(${TARGET}) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 2ee2132bf..a08ed79c8 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -503,11 +503,17 @@ #define TUP_DCD_ENDPOINT_MAX 8 #elif TU_CHECK_MCU(OPT_MCU_CH32V20X) - // v20x support both FSDEV (USBD) and USBFS, default to FSDEV + // v20x support both port0 FSDEV (USBD) and port1 USBFS #define TUP_USBIP_WCH_USBFS + + #ifndef CFG_TUH_WCH_USBIP_USBFS + #define CFG_TUH_WCH_USBIP_USBFS 1 + #endif + #define TUP_USBIP_FSDEV #define TUP_USBIP_FSDEV_CH32 + // default to FSDEV for device #if !defined(CFG_TUD_WCH_USBIP_USBFS) #define CFG_TUD_WCH_USBIP_USBFS 0 #endif diff --git a/src/portable/wch/dcd_ch32_usbhs.c b/src/portable/wch/dcd_ch32_usbhs.c index f8bf3c889..4a208b9df 100644 --- a/src/portable/wch/dcd_ch32_usbhs.c +++ b/src/portable/wch/dcd_ch32_usbhs.c @@ -27,7 +27,7 @@ #include "tusb_option.h" -#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && CFG_TUD_WCH_USBIP_USBHS +#if CFG_TUD_ENABLED && defined(TUP_USBIP_WCH_USBHS) && defined(CFG_TUD_WCH_USBIP_USBHS) && CFG_TUD_WCH_USBIP_USBHS #include "ch32_usbhs_reg.h" #include "device/dcd.h" diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index 800390989..d176f40c5 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -37,20 +37,20 @@ #include "ch32v20x.h" #include "ch32v20x_usb.h" -void osal_task_delay(uint32_t msec) { - uint32_t start = board_millis(); - while (board_millis() - start < msec) {} -} - #define USBFS_RX_BUF_LEN 64 #define USBFS_TX_BUF_LEN 64 -__attribute__((aligned(4))) static uint8_t USBFS_RX_Buf[USBFS_RX_BUF_LEN]; -__attribute__((aligned(4))) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN]; +TU_ATTR_ALIGNED(4) static uint8_t USBFS_RX_Buf[USBFS_RX_BUF_LEN]; +TU_ATTR_ALIGNED(4) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN]; #define USB_XFER_TIMEOUT_MILLIS 100 // #define USB_INTERRUPT_XFER_TIMEOUT_MILLIS 1 -#define PANIC(...) do { printf("%s() L%d: ", __func__, __LINE__); printf("\r\n[PANIC] " __VA_ARGS__); while (true) { } } while (false) +#define PANIC(...) \ + do { \ + printf("%s() L%d: ", __func__, __LINE__); \ + printf("\r\n[PANIC] " __VA_ARGS__); \ + while (true) {} \ + } while (false) #define LOG_CH32_USBFSH(...) TU_LOG3(__VA_ARGS__) @@ -70,106 +70,87 @@ __attribute__((aligned(4))) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN]; // Endpoint status -typedef struct usb_edpt -{ - // Is this a valid struct - bool configured; +typedef struct usb_edpt { + // Is this a valid struct + bool configured; - uint8_t dev_addr; - uint8_t ep_addr; - uint8_t max_packet_size; + uint8_t dev_addr; + uint8_t ep_addr; + uint8_t max_packet_size; - uint8_t xfer_type; + uint8_t xfer_type; - // Data toggle (0 or not 0) for DATA0/1 - uint8_t data_toggle; + // Data toggle (0 or not 0) for DATA0/1 + uint8_t data_toggle; } usb_edpt_t; - static usb_edpt_t usb_edpt_list[CFG_TUH_DEVICE_MAX * 6] = {}; - typedef struct usb_current_xfer_st { - bool is_busy; - uint8_t dev_addr; - uint8_t ep_addr; - // Xfer started time in millis for timeout - uint32_t start_ms; - uint8_t* buffer; - uint16_t bufferlen; - uint16_t xferred_len; + bool is_busy; + uint8_t dev_addr; + uint8_t ep_addr; + // Xfer started time in millis for timeout + uint32_t start_ms; + uint8_t *buffer; + uint16_t bufferlen; + uint16_t xferred_len; } usb_current_xfer_t; static volatile usb_current_xfer_t usb_current_xfer_info = {}; - -static usb_edpt_t* get_edpt_record(uint8_t dev_addr, uint8_t ep_addr) -{ - for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) - { - usb_edpt_t* cur = &usb_edpt_list[i]; - if (cur->configured && cur->dev_addr == dev_addr && cur->ep_addr == ep_addr) - { - return cur; - } +static usb_edpt_t *get_edpt_record(uint8_t dev_addr, uint8_t ep_addr) { + for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) { + usb_edpt_t *cur = &usb_edpt_list[i]; + if (cur->configured && cur->dev_addr == dev_addr && cur->ep_addr == ep_addr) { + return cur; } - return NULL; + } + return NULL; } -static usb_edpt_t* get_empty_record_slot(void) -{ - for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) - { - if (!usb_edpt_list[i].configured) - { - return &usb_edpt_list[i]; - } +static usb_edpt_t *get_empty_record_slot(void) { + for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) { + if (!usb_edpt_list[i].configured) { + return &usb_edpt_list[i]; } - return NULL; + } + return NULL; } -static usb_edpt_t* add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type) -{ - usb_edpt_t* slot = get_empty_record_slot(); - if (slot == NULL) { - PANIC("add_edpt_record(0x%02x, 0x%02x, ...) no slot for new record\r\n", dev_addr, ep_addr); - } - TU_ASSERT(slot != NULL, NULL); +static usb_edpt_t *add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type) { + usb_edpt_t *slot = get_empty_record_slot(); + if (slot == NULL) { + PANIC("add_edpt_record(0x%02x, 0x%02x, ...) no slot for new record\r\n", dev_addr, ep_addr); + } + TU_ASSERT(slot != NULL, NULL); - slot->dev_addr = dev_addr; - slot->ep_addr = ep_addr; - slot->max_packet_size = max_packet_size; - slot->xfer_type = xfer_type; - slot->data_toggle = 0; + slot->dev_addr = dev_addr; + slot->ep_addr = ep_addr; + slot->max_packet_size = max_packet_size; + slot->xfer_type = xfer_type; + slot->data_toggle = 0; - slot->configured = true; + slot->configured = true; - return slot; + return slot; } -static usb_edpt_t* get_or_add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type) -{ - usb_edpt_t* ret = get_edpt_record(dev_addr, ep_addr); - if (ret != NULL) - { - return ret; - } - else - { - return add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type); - } +static usb_edpt_t *get_or_add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type) { + usb_edpt_t *ret = get_edpt_record(dev_addr, ep_addr); + if (ret != NULL) { + return ret; + } else { + return add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type); + } } - -static void remove_edpt_record_for_device(uint8_t dev_addr) -{ - for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) - { - if (usb_edpt_list[i].configured && usb_edpt_list[i].dev_addr == dev_addr) - { - usb_edpt_list[i].configured = false; - } +static void remove_edpt_record_for_device(uint8_t dev_addr) { + for (size_t i = 0; i < TU_ARRAY_SIZE(usb_edpt_list); i++) { + if (usb_edpt_list[i].configured && usb_edpt_list[i].dev_addr == dev_addr) { + usb_edpt_list[i].configured = false; } + } } // static void dump_edpt_record_list() { @@ -183,544 +164,462 @@ static void remove_edpt_record_for_device(uint8_t dev_addr) // } // } - static bool interrupt_enabled = false; /** Enable or disable USBFS Host function */ -static void hardware_init_host(bool enabled) -{ - // Reset USBOTG module - USBOTG_H_FS->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL; +static void hardware_init_host(bool enabled) { + // Reset USBOTG module + USBOTG_H_FS->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL; - osal_task_delay(1); + tusb_time_delay_ms_api(1); + USBOTG_H_FS->BASE_CTRL = 0; + + if (!enabled) { + // Disable all feature USBOTG_H_FS->BASE_CTRL = 0; - - if (!enabled) - { - // Disable all feature - USBOTG_H_FS->BASE_CTRL = 0; - } - else - { - // Enable USB Host features - // NVIC_DisableIRQ(USBFS_IRQn); - hcd_int_disable(0); - USBOTG_H_FS->BASE_CTRL = USBFS_UC_HOST_MODE | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN; - USBOTG_H_FS->HOST_EP_MOD = USBFS_UH_EP_TX_EN | USBFS_UH_EP_RX_EN; - USBOTG_H_FS->HOST_RX_DMA = (uint32_t)USBFS_RX_Buf; - USBOTG_H_FS->HOST_TX_DMA = (uint32_t)USBFS_TX_Buf; - // USBOTG_H_FS->INT_EN = USBFS_UIE_TRANSFER | USBFS_UIE_DETECT; - USBOTG_H_FS->INT_EN = USBFS_UIE_DETECT; - } + } else { + // Enable USB Host features + // NVIC_DisableIRQ(USBFS_IRQn); + hcd_int_disable(0); + USBOTG_H_FS->BASE_CTRL = USBFS_UC_HOST_MODE | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN; + USBOTG_H_FS->HOST_EP_MOD = USBFS_UH_EP_TX_EN | USBFS_UH_EP_RX_EN; + USBOTG_H_FS->HOST_RX_DMA = (uint32_t) USBFS_RX_Buf; + USBOTG_H_FS->HOST_TX_DMA = (uint32_t) USBFS_TX_Buf; + // USBOTG_H_FS->INT_EN = USBFS_UIE_TRANSFER | USBFS_UIE_DETECT; + USBOTG_H_FS->INT_EN = USBFS_UIE_DETECT; + } } -static bool hardware_start_xfer(uint8_t pid, uint8_t ep_addr, uint8_t data_toggle) -{ - LOG_CH32_USBFSH("hardware_start_xfer(pid=%s(0x%02x), ep_addr=0x%02x, toggle=%d)\r\n", - pid == USB_PID_IN ? "IN" : pid == USB_PID_OUT ? "OUT" : pid == USB_PID_SETUP ? "SETUP" : "(other)", - pid, ep_addr, data_toggle); +static bool hardware_start_xfer(uint8_t pid, uint8_t ep_addr, uint8_t data_toggle) { + LOG_CH32_USBFSH("hardware_start_xfer(pid=%s(0x%02x), ep_addr=0x%02x, toggle=%d)\r\n", + pid == USB_PID_IN ? "IN" : pid == USB_PID_OUT ? "OUT" + : pid == USB_PID_SETUP ? "SETUP" + : "(other)", + pid, ep_addr, data_toggle); - // if (pid == USB_PID_IN) - // { // FIXME: long delay needed (at release build) about 30msec - // loopdelay(SystemCoreClock / 1000 * 30); - // } + // if (pid == USB_PID_IN) + // { // FIXME: long delay needed (at release build) about 30msec + // loopdelay(SystemCoreClock / 1000 * 30); + // } - uint8_t pid_edpt = (pid << 4) | (tu_edpt_number(ep_addr) & 0x0f); - USBOTG_H_FS->HOST_TX_CTRL = (data_toggle != 0) ? USBFS_UH_T_TOG : 0; - USBOTG_H_FS->HOST_RX_CTRL = (data_toggle != 0) ? USBFS_UH_R_TOG : 0; - USBOTG_H_FS->HOST_EP_PID = pid_edpt; - USBOTG_H_FS->INT_EN |= USBFS_UIE_TRANSFER; - USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; - return true; + uint8_t pid_edpt = (pid << 4) | (tu_edpt_number(ep_addr) & 0x0f); + USBOTG_H_FS->HOST_TX_CTRL = (data_toggle != 0) ? USBFS_UH_T_TOG : 0; + USBOTG_H_FS->HOST_RX_CTRL = (data_toggle != 0) ? USBFS_UH_R_TOG : 0; + USBOTG_H_FS->HOST_EP_PID = pid_edpt; + USBOTG_H_FS->INT_EN |= USBFS_UIE_TRANSFER; + USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; + return true; } /** Set device address to communicate */ -static void hardware_update_device_address(uint8_t dev_addr) -{ - // Keep the bit of GP_BIT. Other 7bits are actual device address. - USBOTG_H_FS->DEV_ADDR = (USBOTG_H_FS->DEV_ADDR & USBFS_UDA_GP_BIT) | (dev_addr & USBFS_USB_ADDR_MASK); +static void hardware_update_device_address(uint8_t dev_addr) { + // Keep the bit of GP_BIT. Other 7bits are actual device address. + USBOTG_H_FS->DEV_ADDR = (USBOTG_H_FS->DEV_ADDR & USBFS_UDA_GP_BIT) | (dev_addr & USBFS_USB_ADDR_MASK); } /** Set port speed */ -static void hardware_update_port_speed(tusb_speed_t speed) -{ - LOG_CH32_USBFSH("hardware_update_port_speed(%s)\r\n", speed == TUSB_SPEED_FULL ? "Full" : speed == TUSB_SPEED_LOW ? "Low" : "(invalid)"); - switch (speed) { +static void hardware_update_port_speed(tusb_speed_t speed) { + LOG_CH32_USBFSH("hardware_update_port_speed(%s)\r\n", speed == TUSB_SPEED_FULL ? "Full" : speed == TUSB_SPEED_LOW ? "Low" + : "(invalid)"); + switch (speed) { case TUSB_SPEED_LOW: - USBOTG_H_FS->BASE_CTRL |= USBFS_UC_LOW_SPEED; - USBOTG_H_FS->HOST_CTRL |= USBFS_UH_LOW_SPEED; - USBOTG_H_FS->HOST_SETUP |= USBFS_UH_PRE_PID_EN; - return; + USBOTG_H_FS->BASE_CTRL |= USBFS_UC_LOW_SPEED; + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_LOW_SPEED; + USBOTG_H_FS->HOST_SETUP |= USBFS_UH_PRE_PID_EN; + return; case TUSB_SPEED_FULL: - USBOTG_H_FS->BASE_CTRL &= ~USBFS_UC_LOW_SPEED; - USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED; - USBOTG_H_FS->HOST_SETUP &= ~USBFS_UH_PRE_PID_EN; - return; + USBOTG_H_FS->BASE_CTRL &= ~USBFS_UC_LOW_SPEED; + USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED; + USBOTG_H_FS->HOST_SETUP &= ~USBFS_UH_PRE_PID_EN; + return; default: - PANIC("hardware_update_port_speed(%d)\r\n", speed); - } + PANIC("hardware_update_port_speed(%d)\r\n", speed); + } } - static void hardware_set_port_address_speed(uint8_t dev_addr) { - hardware_update_device_address(dev_addr); - tusb_speed_t rhport_speed = hcd_port_speed_get(0); - tusb_speed_t dev_speed = tuh_speed_get(dev_addr); - hardware_update_port_speed(dev_speed); - if (rhport_speed == TUSB_SPEED_FULL && dev_speed == TUSB_SPEED_LOW) { - USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED; - } + hardware_update_device_address(dev_addr); + tusb_speed_t rhport_speed = hcd_port_speed_get(0); + tusb_speed_t dev_speed = tuh_speed_get(dev_addr); + hardware_update_port_speed(dev_speed); + if (rhport_speed == TUSB_SPEED_FULL && dev_speed == TUSB_SPEED_LOW) { + USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_LOW_SPEED; + } } - -static bool hardware_device_attached(void) -{ - return USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH; +static bool hardware_device_attached(void) { + return USBOTG_H_FS->MIS_ST & USBFS_UMS_DEV_ATTACH; } - //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ -bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) -{ - (void)rhport; - (void)rh_init; - hardware_init_host(true); +bool hcd_init(uint8_t rhport, const tusb_rhport_init_t *rh_init) { + (void) rhport; + (void) rh_init; + hardware_init_host(true); - return true; + return true; } -bool hcd_deinit(uint8_t rhport) -{ - (void)rhport; - hardware_init_host(false); +bool hcd_deinit(uint8_t rhport) { + (void) rhport; + hardware_init_host(false); - return true; + return true; } - static bool int_state_for_portreset = false; -void hcd_port_reset(uint8_t rhport) -{ - (void)rhport; - LOG_CH32_USBFSH("hcd_port_reset()\r\n"); - int_state_for_portreset = interrupt_enabled; - // NVIC_DisableIRQ(USBFS_IRQn); - hcd_int_disable(rhport); - hardware_update_device_address(0x00); +void hcd_port_reset(uint8_t rhport) { + (void) rhport; + LOG_CH32_USBFSH("hcd_port_reset()\r\n"); + int_state_for_portreset = interrupt_enabled; + // NVIC_DisableIRQ(USBFS_IRQn); + hcd_int_disable(rhport); + hardware_update_device_address(0x00); - // USBOTG_H_FS->HOST_SETUP = 0x00; + // USBOTG_H_FS->HOST_SETUP = 0x00; - USBOTG_H_FS->HOST_CTRL |= USBFS_UH_BUS_RESET; + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_BUS_RESET; - return; + return; } -void hcd_port_reset_end(uint8_t rhport) -{ - (void)rhport; - LOG_CH32_USBFSH("hcd_port_reset_end()\r\n"); +void hcd_port_reset_end(uint8_t rhport) { + (void) rhport; + LOG_CH32_USBFSH("hcd_port_reset_end()\r\n"); - USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_BUS_RESET; - osal_task_delay(2); + USBOTG_H_FS->HOST_CTRL &= ~USBFS_UH_BUS_RESET; + tusb_time_delay_ms_api(2); - if ((USBOTG_H_FS->HOST_CTRL & USBFS_UH_PORT_EN) == 0) - { - if (hcd_port_speed_get(0) == TUSB_SPEED_LOW) - { - hardware_update_port_speed(TUSB_SPEED_LOW); - } + if ((USBOTG_H_FS->HOST_CTRL & USBFS_UH_PORT_EN) == 0) { + if (hcd_port_speed_get(0) == TUSB_SPEED_LOW) { + hardware_update_port_speed(TUSB_SPEED_LOW); } + } - USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; - USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; + USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; - // Suppress the attached event - USBOTG_H_FS->INT_FG |= USBFS_UIF_DETECT; + // Suppress the attached event + USBOTG_H_FS->INT_FG |= USBFS_UIF_DETECT; - if (int_state_for_portreset) { - hcd_int_enable(rhport); - } - - return; + if (int_state_for_portreset) { + hcd_int_enable(rhport); + } } -bool hcd_port_connect_status(uint8_t rhport) -{ - (void)rhport; +bool hcd_port_connect_status(uint8_t rhport) { + (void) rhport; - return hardware_device_attached(); + return hardware_device_attached(); } -tusb_speed_t hcd_port_speed_get(uint8_t rhport) -{ - (void)rhport; - if (USBOTG_H_FS->MIS_ST & USBFS_UMS_DM_LEVEL) - { - return TUSB_SPEED_LOW; - } - else - { - return TUSB_SPEED_FULL; - } +tusb_speed_t hcd_port_speed_get(uint8_t rhport) { + (void) rhport; + if (USBOTG_H_FS->MIS_ST & USBFS_UMS_DM_LEVEL) { + return TUSB_SPEED_LOW; + } else { + return TUSB_SPEED_FULL; + } } // Close all opened endpoint belong to this device -void hcd_device_close(uint8_t rhport, uint8_t dev_addr) -{ - (void)rhport; - LOG_CH32_USBFSH("hcd_device_close(%d, 0x%02x)\r\n", rhport, dev_addr); - remove_edpt_record_for_device(dev_addr); +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { + (void) rhport; + LOG_CH32_USBFSH("hcd_device_close(%d, 0x%02x)\r\n", rhport, dev_addr); + remove_edpt_record_for_device(dev_addr); +} +uint32_t hcd_frame_number(uint8_t rhport) { + (void) rhport; + + return board_millis(); +} + +void hcd_int_enable(uint8_t rhport) { + (void) rhport; + NVIC_EnableIRQ(USBFS_IRQn); + interrupt_enabled = true; +} + +void hcd_int_disable(uint8_t rhport) { + (void) rhport; + NVIC_DisableIRQ(USBFS_IRQn); + interrupt_enabled = false; +} + +void hcd_int_handler(uint8_t rhport, bool in_isr) { + (void) rhport; + (void) in_isr; + + if (USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT) { + // Clear the flag + USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT; + // Read the detection state + bool attached = hardware_device_attached(); + LOG_CH32_USBFSH("hcd_int_handler() attached = %d\r\n", attached ? 1 : 0); + if (attached) { + hcd_event_device_attach(rhport, true); + } else { + hcd_event_device_remove(rhport, true); + } return; -} + } -uint32_t hcd_frame_number(uint8_t rhport) -{ - (void)rhport; + if (USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER) { + // Disable transfer interrupt + USBOTG_H_FS->INT_EN &= ~USBFS_UIE_TRANSFER; + // Clear the flag + // USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; + // Copy PID and Endpoint + uint8_t pid_edpt = USBOTG_H_FS->HOST_EP_PID; + uint8_t status = USBOTG_H_FS->INT_ST; + uint8_t dev_addr = USBOTG_H_FS->DEV_ADDR & USBFS_USB_ADDR_MASK; + // Clear register to stop transfer + // USBOTG_H_FS->HOST_EP_PID = 0x00; - return board_millis(); -} + LOG_CH32_USBFSH("hcd_int_handler() pid_edpt=0x%02x\r\n", pid_edpt); -void hcd_int_enable(uint8_t rhport) -{ - (void)rhport; - NVIC_EnableIRQ(USBFS_IRQn); - interrupt_enabled = true; + uint8_t request_pid = pid_edpt >> 4; + uint8_t response_pid = status & USBFS_UIS_H_RES_MASK; + uint8_t ep_addr = pid_edpt & 0x0f; + if (request_pid == USB_PID_IN) { + ep_addr |= 0x80; + } - return; -} + usb_edpt_t *edpt_info = get_edpt_record(dev_addr, ep_addr); + if (edpt_info == NULL) { + PANIC("\r\nget_edpt_record(0x%02x, 0x%02x) returned NULL in USBHD_IRQHandler\r\n", dev_addr, ep_addr); + } -void hcd_int_disable(uint8_t rhport) -{ - (void)rhport; - NVIC_DisableIRQ(USBFS_IRQn); - interrupt_enabled = false; + if (status & USBFS_UIS_TOG_OK) { + edpt_info->data_toggle ^= 0x01; - return; -} - -void hcd_int_handler(uint8_t rhport, bool in_isr) -{ - (void)rhport; - (void)in_isr; - - if (USBOTG_H_FS->INT_FG & USBFS_UIF_DETECT) - { - // Clear the flag - USBOTG_H_FS->INT_FG = USBFS_UIF_DETECT; - // Read the detection state - bool attached = hardware_device_attached(); - LOG_CH32_USBFSH("hcd_int_handler() attached = %d\r\n", attached ? 1 : 0); - if (attached) - { - hcd_event_device_attach(rhport, true); + switch (request_pid) { + case USB_PID_SETUP: + case USB_PID_OUT: { + uint16_t tx_len = USBOTG_H_FS->HOST_TX_LEN; + usb_current_xfer_info.bufferlen -= tx_len; + usb_current_xfer_info.xferred_len += tx_len; + if (usb_current_xfer_info.bufferlen == 0) { + LOG_CH32_USBFSH("USB_PID_%s completed %d bytes\r\n", request_pid == USB_PID_OUT ? "OUT" : "SETUP", usb_current_xfer_info.xferred_len); + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, usb_current_xfer_info.xferred_len, XFER_RESULT_SUCCESS, true); + return; + } else { + LOG_CH32_USBFSH("USB_PID_OUT continue...\r\n"); + usb_current_xfer_info.buffer += tx_len; + uint16_t copylen = USBFS_TX_BUF_LEN; + if (copylen > usb_current_xfer_info.bufferlen) { + copylen = usb_current_xfer_info.bufferlen; + } + memcpy(USBFS_TX_Buf, usb_current_xfer_info.buffer, copylen); + hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); + return; + } } - else - { - hcd_event_device_remove(rhport, true); + case USB_PID_IN: { + uint16_t received_len = USBOTG_H_FS->RX_LEN; + usb_current_xfer_info.xferred_len += received_len; + uint16_t xferred_len = usb_current_xfer_info.xferred_len; + LOG_CH32_USBFSH("Read %d bytes\r\n", received_len); + // if (received_len > 0 && (usb_current_xfer_info.buffer == NULL || usb_current_xfer_info.bufferlen == 0)) { + // PANIC("Data received but buffer not set\r\n"); + // } + memcpy(usb_current_xfer_info.buffer, USBFS_RX_Buf, received_len); + usb_current_xfer_info.buffer += received_len; + if ((received_len < edpt_info->max_packet_size) || (xferred_len == usb_current_xfer_info.bufferlen)) { + // USB device sent all data. + LOG_CH32_USBFSH("USB_PID_IN completed\r\n"); + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); + return; + } else { + // USB device may send more data. + LOG_CH32_USBFSH("Read more data\r\n"); + hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); + return; + } + } + default: { + PANIC("Unknown PID: 0x%02x\n", request_pid); + } + } + } else { + if (response_pid == USB_PID_STALL) { + LOG_CH32_USBFSH("STALL response\r\n"); + hcd_edpt_clear_stall(0, dev_addr, ep_addr); + edpt_info->data_toggle = 0; + hardware_start_xfer(request_pid, ep_addr, 0); + return; + } else if (response_pid == USB_PID_NAK) { + LOG_CH32_USBFSH("NAK reposense\r\n"); + uint32_t elapsed_time = board_millis() - usb_current_xfer_info.start_ms; + if (edpt_info->xfer_type == TUSB_XFER_INTERRUPT) { + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, true); + } else if (elapsed_time > USB_XFER_TIMEOUT_MILLIS) { + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + } else { + hardware_start_xfer(request_pid, ep_addr, edpt_info->data_toggle); } return; + } else if (response_pid == USB_PID_DATA0 || response_pid == USB_PID_DATA1) { + LOG_CH32_USBFSH("Data toggle mismatched and DATA0/1 (not STALL). RX_LEN=%d\r\n", USBOTG_H_FS->RX_LEN); + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + return; + } else { + LOG_CH32_USBFSH("In USBHD_IRQHandler, unexpected response PID: 0x%02x\r\n", response_pid); + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + return; + } } - - if (USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER) - { - // Disable transfer interrupt - USBOTG_H_FS->INT_EN &= ~USBFS_UIE_TRANSFER; - // Clear the flag - // USBOTG_H_FS->INT_FG = USBFS_UIF_TRANSFER; - // Copy PID and Endpoint - uint8_t pid_edpt = USBOTG_H_FS->HOST_EP_PID; - uint8_t status = USBOTG_H_FS->INT_ST; - uint8_t dev_addr = USBOTG_H_FS->DEV_ADDR & USBFS_USB_ADDR_MASK; - // Clear register to stop transfer - // USBOTG_H_FS->HOST_EP_PID = 0x00; - - LOG_CH32_USBFSH("hcd_int_handler() pid_edpt=0x%02x\r\n", pid_edpt); - - uint8_t request_pid = pid_edpt >> 4; - uint8_t response_pid = status & USBFS_UIS_H_RES_MASK; - uint8_t ep_addr = pid_edpt & 0x0f; - if (request_pid == USB_PID_IN) - { - ep_addr |= 0x80; - } - - usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr); - if (edpt_info == NULL) - { - PANIC("\r\nget_edpt_record(0x%02x, 0x%02x) returned NULL in USBHD_IRQHandler\r\n", dev_addr, ep_addr); - } - - if (status & USBFS_UIS_TOG_OK) - { - edpt_info->data_toggle ^= 0x01; - - switch (request_pid) - { - case USB_PID_SETUP: - case USB_PID_OUT: - { - uint16_t tx_len = USBOTG_H_FS->HOST_TX_LEN; - usb_current_xfer_info.bufferlen -= tx_len; - usb_current_xfer_info.xferred_len += tx_len; - if (usb_current_xfer_info.bufferlen == 0) - { - LOG_CH32_USBFSH("USB_PID_%s completed %d bytes\r\n", request_pid == USB_PID_OUT ? "OUT" : "SETUP", usb_current_xfer_info.xferred_len); - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, usb_current_xfer_info.xferred_len, XFER_RESULT_SUCCESS, true); - return; - } - else - { - LOG_CH32_USBFSH("USB_PID_OUT continue...\r\n"); - usb_current_xfer_info.buffer += tx_len; - uint16_t copylen = USBFS_TX_BUF_LEN; - if (copylen > usb_current_xfer_info.bufferlen) - { - copylen = usb_current_xfer_info.bufferlen; - } - memcpy(USBFS_TX_Buf, usb_current_xfer_info.buffer, copylen); - hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); - return; - } - } - case USB_PID_IN: - { - uint16_t received_len = USBOTG_H_FS->RX_LEN; - usb_current_xfer_info.xferred_len += received_len; - uint16_t xferred_len = usb_current_xfer_info.xferred_len; - LOG_CH32_USBFSH("Read %d bytes\r\n", received_len); - // if (received_len > 0 && (usb_current_xfer_info.buffer == NULL || usb_current_xfer_info.bufferlen == 0)) { - // PANIC("Data received but buffer not set\r\n"); - // } - memcpy(usb_current_xfer_info.buffer, USBFS_RX_Buf, received_len); - usb_current_xfer_info.buffer += received_len; - if ((received_len < edpt_info->max_packet_size) || (xferred_len == usb_current_xfer_info.bufferlen)) - { - // USB device sent all data. - LOG_CH32_USBFSH("USB_PID_IN completed\r\n"); - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); - return; - } - else - { - // USB device may send more data. - LOG_CH32_USBFSH("Read more data\r\n"); - hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); - return; - } - } - default: - { - PANIC("Unknown PID: 0x%02x\n", request_pid); - } - } - } - else - { - if (response_pid == USB_PID_STALL) - { - LOG_CH32_USBFSH("STALL response\r\n"); - hcd_edpt_clear_stall(0, dev_addr, ep_addr); - edpt_info->data_toggle = 0; - hardware_start_xfer(request_pid, ep_addr, 0); - return; - } - else if (response_pid == USB_PID_NAK) - { - LOG_CH32_USBFSH("NAK reposense\r\n"); - uint32_t elapsed_time = board_millis() - usb_current_xfer_info.start_ms; - if (edpt_info->xfer_type == TUSB_XFER_INTERRUPT) - { - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, true); - } - else if (elapsed_time > USB_XFER_TIMEOUT_MILLIS) - { - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); - } - else - { - hardware_start_xfer(request_pid, ep_addr, edpt_info->data_toggle); - } - return; - } - else if (response_pid == USB_PID_DATA0 || response_pid == USB_PID_DATA1) - { - LOG_CH32_USBFSH("Data toggle mismatched and DATA0/1 (not STALL). RX_LEN=%d\r\n", USBOTG_H_FS->RX_LEN); - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); - return; - } - else - { - LOG_CH32_USBFSH("In USBHD_IRQHandler, unexpected response PID: 0x%02x\r\n", response_pid); - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); - return; - } - } - } + } } //--------------------------------------------------------------------+ // Endpoint API //--------------------------------------------------------------------+ -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) -{ - (void)rhport; - uint8_t ep_addr = ep_desc->bEndpointAddress; - uint8_t ep_num = tu_edpt_number(ep_addr); - uint16_t max_packet_size = ep_desc->wMaxPacketSize; - uint8_t xfer_type = ep_desc->bmAttributes.xfer; - LOG_CH32_USBFSH("hcd_edpt_open(rhport=%d, dev_addr=0x%02x, %p) EndpointAdderss=0x%02x,maxPacketSize=%d,xfer_type=%d\r\n", rhport, dev_addr, ep_desc, ep_addr, max_packet_size, xfer_type); +bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc) { + (void) rhport; + uint8_t ep_addr = ep_desc->bEndpointAddress; + uint8_t ep_num = tu_edpt_number(ep_addr); + uint16_t max_packet_size = ep_desc->wMaxPacketSize; + uint8_t xfer_type = ep_desc->bmAttributes.xfer; + LOG_CH32_USBFSH("hcd_edpt_open(rhport=%d, dev_addr=0x%02x, %p) EndpointAdderss=0x%02x,maxPacketSize=%d,xfer_type=%d\r\n", rhport, dev_addr, ep_desc, ep_addr, max_packet_size, xfer_type); - if (ep_num == 0x00) - { - TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x00, max_packet_size, xfer_type) != NULL, false); - TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x80, max_packet_size, xfer_type) != NULL, false); - } - else - { - TU_ASSERT(get_or_add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type) != NULL, false); - } + if (ep_num == 0x00) { + TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x00, max_packet_size, xfer_type) != NULL, false); + TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x80, max_packet_size, xfer_type) != NULL, false); + } else { + TU_ASSERT(get_or_add_edpt_record(dev_addr, ep_addr, max_packet_size, xfer_type) != NULL, false); + } + USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; + USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; - USBOTG_H_FS->HOST_CTRL |= USBFS_UH_PORT_EN; - USBOTG_H_FS->HOST_SETUP |= USBFS_UH_SOF_EN; + hardware_set_port_address_speed(dev_addr); - hardware_set_port_address_speed(dev_addr); - - return true; + return true; } -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) -{ - (void)rhport; +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) { + (void) rhport; - LOG_CH32_USBFSH("hcd_edpt_xfer(%d, 0x%02x, 0x%02x, ...)\r\n", rhport, dev_addr, ep_addr); + LOG_CH32_USBFSH("hcd_edpt_xfer(%d, 0x%02x, 0x%02x, ...)\r\n", rhport, dev_addr, ep_addr); - while (usb_current_xfer_info.is_busy) { } + while (usb_current_xfer_info.is_busy) {} + usb_current_xfer_info.is_busy = true; - usb_current_xfer_info.is_busy = true; + usb_edpt_t *edpt_info = get_edpt_record(dev_addr, ep_addr); + if (edpt_info == NULL) { + PANIC("get_edpt_record() returned NULL in hcd_edpt_xfer()\r\n"); + } - usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr); - if (edpt_info == NULL) - { - PANIC("get_edpt_record() returned NULL in hcd_edpt_xfer()\r\n"); - } - - hardware_set_port_address_speed(dev_addr); - - usb_current_xfer_info.dev_addr = dev_addr; - usb_current_xfer_info.ep_addr = ep_addr; - usb_current_xfer_info.buffer = buffer; - usb_current_xfer_info.bufferlen = buflen; - usb_current_xfer_info.start_ms = board_millis(); - usb_current_xfer_info.xferred_len = 0; - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) - { - LOG_CH32_USBFSH("hcd_edpt_xfer(): READ, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); - return hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); - } - else - { - LOG_CH32_USBFSH("hcd_edpt_xfer(): WRITE, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); - uint16_t copylen = USBFS_TX_BUF_LEN; - if (copylen > buflen) - { - copylen = buflen; - } - USBOTG_H_FS->HOST_TX_LEN = copylen; - memcpy(USBFS_TX_Buf, buffer, copylen); - return hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); + hardware_set_port_address_speed(dev_addr); + + usb_current_xfer_info.dev_addr = dev_addr; + usb_current_xfer_info.ep_addr = ep_addr; + usb_current_xfer_info.buffer = buffer; + usb_current_xfer_info.bufferlen = buflen; + usb_current_xfer_info.start_ms = board_millis(); + usb_current_xfer_info.xferred_len = 0; + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { + LOG_CH32_USBFSH("hcd_edpt_xfer(): READ, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); + return hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); + } else { + LOG_CH32_USBFSH("hcd_edpt_xfer(): WRITE, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); + uint16_t copylen = USBFS_TX_BUF_LEN; + if (copylen > buflen) { + copylen = buflen; } + USBOTG_H_FS->HOST_TX_LEN = copylen; + memcpy(USBFS_TX_Buf, buffer, copylen); + return hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); + } } -bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) -{ - (void) rhport; - (void) dev_addr; - (void) ep_addr; +bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + (void) ep_addr; - return false; + return false; } -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ - (void)rhport; - - while (usb_current_xfer_info.is_busy) { } +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { + (void) rhport; - usb_current_xfer_info.is_busy = true; + while (usb_current_xfer_info.is_busy) {} - LOG_CH32_USBFSH("hcd_setup_send(rhport=%d, dev_addr=0x%02x, %p)\r\n", rhport, dev_addr, setup_packet); + usb_current_xfer_info.is_busy = true; - hardware_set_port_address_speed(dev_addr); + LOG_CH32_USBFSH("hcd_setup_send(rhport=%d, dev_addr=0x%02x, %p)\r\n", rhport, dev_addr, setup_packet); - usb_edpt_t* edpt_info_tx = get_edpt_record(dev_addr, 0x00); - usb_edpt_t* edpt_info_rx = get_edpt_record(dev_addr, 0x80); - TU_ASSERT(edpt_info_tx != NULL, false); - TU_ASSERT(edpt_info_rx != NULL, false); + hardware_set_port_address_speed(dev_addr); - // Initialize data toggle (SETUP always starts with DATA0) - // Data toggle for OUT is toggled in hcd_int_handler() - edpt_info_tx->data_toggle = 0; - // Data toggle for IN must be set 0x01 manually. - edpt_info_rx->data_toggle = 0x01; - const uint16_t setup_packet_datalen = 8; - memcpy(USBFS_TX_Buf, setup_packet, setup_packet_datalen); - USBOTG_H_FS->HOST_TX_LEN = setup_packet_datalen; - uint8_t ep_addr = (setup_packet[0] & 0x80) ? 0x80 : 0x00; - usb_current_xfer_info.dev_addr = dev_addr; - usb_current_xfer_info.ep_addr = ep_addr; - usb_current_xfer_info.start_ms = board_millis(); - usb_current_xfer_info.buffer = USBFS_TX_Buf; - usb_current_xfer_info.bufferlen = setup_packet_datalen; - usb_current_xfer_info.xferred_len = 0; + usb_edpt_t *edpt_info_tx = get_edpt_record(dev_addr, 0x00); + usb_edpt_t *edpt_info_rx = get_edpt_record(dev_addr, 0x80); + TU_ASSERT(edpt_info_tx != NULL, false); + TU_ASSERT(edpt_info_rx != NULL, false); - hardware_start_xfer(USB_PID_SETUP, 0, 0); + // Initialize data toggle (SETUP always starts with DATA0) + // Data toggle for OUT is toggled in hcd_int_handler() + edpt_info_tx->data_toggle = 0; + // Data toggle for IN must be set 0x01 manually. + edpt_info_rx->data_toggle = 0x01; + const uint16_t setup_packet_datalen = 8; + memcpy(USBFS_TX_Buf, setup_packet, setup_packet_datalen); + USBOTG_H_FS->HOST_TX_LEN = setup_packet_datalen; + uint8_t ep_addr = (setup_packet[0] & 0x80) ? 0x80 : 0x00; + usb_current_xfer_info.dev_addr = dev_addr; + usb_current_xfer_info.ep_addr = ep_addr; + usb_current_xfer_info.start_ms = board_millis(); + usb_current_xfer_info.buffer = USBFS_TX_Buf; + usb_current_xfer_info.bufferlen = setup_packet_datalen; + usb_current_xfer_info.xferred_len = 0; - return true; + hardware_start_xfer(USB_PID_SETUP, 0, 0); + + return true; } -bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) -{ - (void) rhport; - (void) dev_addr; - LOG_CH32_USBFSH("hcd_edpt_clear_stall(rhport=%d, dev_addr=0x%02x, ep_addr=0x%02x)\r\n", rhport, dev_addr, ep_addr); - // PANIC("\r\install\r\n"); - uint8_t edpt_num = tu_edpt_number(ep_addr); - uint8_t setup_request_clear_stall[8] = { - 0x02, 0x01, 0x00, 0x00, edpt_num, 0x00, 0x00, 0x00 - }; - memcpy(USBFS_TX_Buf, setup_request_clear_stall, 8); - USBOTG_H_FS->HOST_TX_LEN = 8; +bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { + (void) rhport; + (void) dev_addr; + LOG_CH32_USBFSH("hcd_edpt_clear_stall(rhport=%d, dev_addr=0x%02x, ep_addr=0x%02x)\r\n", rhport, dev_addr, ep_addr); + // PANIC("\r\install\r\n"); + uint8_t edpt_num = tu_edpt_number(ep_addr); + uint8_t setup_request_clear_stall[8] = { + 0x02, 0x01, 0x00, 0x00, edpt_num, 0x00, 0x00, 0x00 + }; + memcpy(USBFS_TX_Buf, setup_request_clear_stall, 8); + USBOTG_H_FS->HOST_TX_LEN = 8; - bool prev_int_state = interrupt_enabled; - hcd_int_disable(0); + bool prev_int_state = interrupt_enabled; + hcd_int_disable(0); - USBOTG_H_FS->HOST_EP_PID = (USB_PID_SETUP << 4) | 0x00; - USBOTG_H_FS->INT_FG |= USBFS_UIF_TRANSFER; - while ((USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER) == 0) { } - USBOTG_H_FS->HOST_EP_PID = 0; - uint8_t response_pid = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK; - (void)response_pid; - LOG_CH32_USBFSH("hcd_edpt_clear_stall() response pid=0x%02x\r\n", response_pid); + USBOTG_H_FS->HOST_EP_PID = (USB_PID_SETUP << 4) | 0x00; + USBOTG_H_FS->INT_FG |= USBFS_UIF_TRANSFER; + while ((USBOTG_H_FS->INT_FG & USBFS_UIF_TRANSFER) == 0) {} + USBOTG_H_FS->HOST_EP_PID = 0; + uint8_t response_pid = USBOTG_H_FS->INT_ST & USBFS_UIS_H_RES_MASK; + (void) response_pid; + LOG_CH32_USBFSH("hcd_edpt_clear_stall() response pid=0x%02x\r\n", response_pid); - if (prev_int_state) { + if (prev_int_state) { hcd_int_enable(0); - } + } - return true; + return true; } #endif From 4b95a70bee078ad34bd916ed83b41cdaa4b00dbc Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 5 Jul 2025 11:37:19 +0700 Subject: [PATCH 263/382] enable ci host and dual build for ch32v20x --- examples/dual/host_hid_to_device_cdc/only.txt | 1 + examples/dual/host_info_to_device_cdc/only.txt | 1 + examples/host/bare_api/only.txt | 1 + examples/host/cdc_msc_hid/only.txt | 1 + examples/host/device_info/only.txt | 1 + examples/host/hid_controller/only.txt | 1 + examples/host/midi_rx/only.txt | 1 + examples/host/msc_file_explorer/only.txt | 1 + 8 files changed, 8 insertions(+) diff --git a/examples/dual/host_hid_to_device_cdc/only.txt b/examples/dual/host_hid_to_device_cdc/only.txt index 3f40b4e7c..35f896f1e 100644 --- a/examples/dual/host_hid_to_device_cdc/only.txt +++ b/examples/dual/host_hid_to_device_cdc/only.txt @@ -1,6 +1,7 @@ board:mimxrt1060_evk board:mimxrt1064_evk board:mcb1800 +mcu:CH32V20X mcu:RP2040 mcu:ra6m5 mcu:MAX3421 diff --git a/examples/dual/host_info_to_device_cdc/only.txt b/examples/dual/host_info_to_device_cdc/only.txt index 3f40b4e7c..35f896f1e 100644 --- a/examples/dual/host_info_to_device_cdc/only.txt +++ b/examples/dual/host_info_to_device_cdc/only.txt @@ -1,6 +1,7 @@ board:mimxrt1060_evk board:mimxrt1064_evk board:mcb1800 +mcu:CH32V20X mcu:RP2040 mcu:ra6m5 mcu:MAX3421 diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt index dcdaf41c7..31dcb108c 100644 --- a/examples/host/bare_api/only.txt +++ b/examples/host/bare_api/only.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt index dcdaf41c7..31dcb108c 100644 --- a/examples/host/cdc_msc_hid/only.txt +++ b/examples/host/cdc_msc_hid/only.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt index b5a4b6739..94ddc73c3 100644 --- a/examples/host/device_info/only.txt +++ b/examples/host/device_info/only.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:ESP32S2 mcu:ESP32S3 mcu:ESP32P4 diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt index dcdaf41c7..31dcb108c 100644 --- a/examples/host/hid_controller/only.txt +++ b/examples/host/hid_controller/only.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt index b5a4b6739..94ddc73c3 100644 --- a/examples/host/midi_rx/only.txt +++ b/examples/host/midi_rx/only.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:ESP32S2 mcu:ESP32S3 mcu:ESP32P4 diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt index dcdaf41c7..31dcb108c 100644 --- a/examples/host/msc_file_explorer/only.txt +++ b/examples/host/msc_file_explorer/only.txt @@ -1,3 +1,4 @@ +mcu:CH32V20X mcu:KINETIS_KL mcu:LPC175X_6X mcu:LPC177X_8X From 3287cfaf76fb37644aa17c2e639d7d59b2764e59 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 5 Jul 2025 12:35:47 +0200 Subject: [PATCH 264/382] Use DMA enable for DCache condition Signed-off-by: HiFiPhile --- src/common/tusb_mcu.h | 15 +++++++++------ src/common/tusb_types.h | 12 ++++++------ src/portable/synopsys/dwc2/dcd_dwc2.c | 2 +- src/portable/synopsys/dwc2/dwc2_stm32.h | 2 +- src/portable/synopsys/dwc2/hcd_dwc2.c | 2 +- src/tusb_option.h | 14 -------------- 6 files changed, 18 insertions(+), 29 deletions(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 8b30c98cd..4205239f1 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -220,8 +220,9 @@ #define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS #endif - #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT 1 - #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT 1 + // Enable dcache if DMA is enabled + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE #define CFG_TUSB_MEM_DCACHE_LINE_SIZE 32 #elif TU_CHECK_MCU(OPT_MCU_STM32H7) @@ -232,8 +233,9 @@ #define TUP_DCD_ENDPOINT_MAX 9 #if __CORTEX_M == 7 - #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT 1 - #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT 1 + // Enable dcache if DMA is enabled + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE #define CFG_TUSB_MEM_DCACHE_LINE_SIZE 32 #endif @@ -333,8 +335,9 @@ // MCU with on-chip HS Phy #define TUP_RHPORT_HIGHSPEED 1 - #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT 1 - #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT 1 + // Enable dcache if DMA is enabled + #define CFG_TUD_MEM_DCACHE_ENABLE_DEFAULT CFG_TUD_DWC2_DMA_ENABLE + #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE #define CFG_TUSB_MEM_DCACHE_LINE_SIZE 32 //--------------------------------------------------------------------+ diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 4735c983a..ee97069bd 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -36,39 +36,39 @@ #endif //------------- Device DCache declaration -------------// -#define TUD_EPBUF_DCACHE_SIZE(_size) (TUD_EPBUF_DCACHE_ALIGNED ? \ +#define TUD_EPBUF_DCACHE_SIZE(_size) (CFG_TUD_MEM_DCACHE_ENABLE ? \ (TU_DIV_CEIL(_size, CFG_TUD_MEM_DCACHE_LINE_SIZE) * CFG_TUD_MEM_DCACHE_LINE_SIZE) : (_size)) // Declare an endpoint buffer with uint8_t[size] #define TUD_EPBUF_DEF(_name, _size) \ union { \ CFG_TUD_MEM_ALIGN uint8_t _name[_size]; \ - TU_ATTR_ALIGNED(TUD_EPBUF_DCACHE_ALIGNED ? CFG_TUD_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUD_EPBUF_DCACHE_SIZE(_size)]; \ + TU_ATTR_ALIGNED(CFG_TUD_MEM_DCACHE_ENABLE ? CFG_TUD_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUD_EPBUF_DCACHE_SIZE(_size)]; \ } // Declare an endpoint buffer with a type #define TUD_EPBUF_TYPE_DEF(_type, _name) \ union { \ CFG_TUD_MEM_ALIGN _type _name; \ - TU_ATTR_ALIGNED(TUD_EPBUF_DCACHE_ALIGNED ? CFG_TUD_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUD_EPBUF_DCACHE_SIZE(sizeof(_type))]; \ + TU_ATTR_ALIGNED(CFG_TUD_MEM_DCACHE_ENABLE ? CFG_TUD_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUD_EPBUF_DCACHE_SIZE(sizeof(_type))]; \ } //------------- Host DCache declaration -------------// -#define TUH_EPBUF_DCACHE_SIZE(_size) (TUH_EPBUF_DCACHE_ALIGNED ? \ +#define TUH_EPBUF_DCACHE_SIZE(_size) (CFG_TUH_MEM_DCACHE_ENABLE ? \ (TU_DIV_CEIL(_size, CFG_TUH_MEM_DCACHE_LINE_SIZE) * CFG_TUH_MEM_DCACHE_LINE_SIZE) : (_size)) // Declare an endpoint buffer with uint8_t[size] #define TUH_EPBUF_DEF(_name, _size) \ union { \ CFG_TUH_MEM_ALIGN uint8_t _name[_size]; \ - TU_ATTR_ALIGNED(TUH_EPBUF_DCACHE_ALIGNED ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUH_EPBUF_DCACHE_SIZE(_size)]; \ + TU_ATTR_ALIGNED(CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUH_EPBUF_DCACHE_SIZE(_size)]; \ } // Declare an endpoint buffer with a type #define TUH_EPBUF_TYPE_DEF(_type, _name) \ union { \ CFG_TUH_MEM_ALIGN _type _name; \ - TU_ATTR_ALIGNED(TUH_EPBUF_DCACHE_ALIGNED ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUH_EPBUF_DCACHE_SIZE(sizeof(_type))]; \ + TU_ATTR_ALIGNED(CFG_TUH_MEM_DCACHE_ENABLE ? CFG_TUH_MEM_DCACHE_LINE_SIZE : 1) uint8_t _name##_dcache_padding[TUH_EPBUF_DCACHE_SIZE(sizeof(_type))]; \ } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index f7e9aacfe..5f86d6b76 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -88,7 +88,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc //-------------------------------------------------------------------- // DMA //-------------------------------------------------------------------- -#if CFG_TUD_MEM_DCACHE_ENABLE && CFG_TUD_DWC2_DMA_ENABLE +#if CFG_TUD_MEM_DCACHE_ENABLE bool dcd_dcache_clean(const void* addr, uint32_t data_size) { TU_VERIFY(addr && data_size); return dwc2_dcache_clean(addr, data_size); diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index f01d11fe8..f9aa5301b 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -280,7 +280,7 @@ static inline void dwc2_phy_update(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { } //------------- DCache -------------// -#if (CFG_TUD_MEM_DCACHE_ENABLE && CFG_TUD_DWC2_DMA_ENABLE) || (CFG_TUH_MEM_DCACHE_ENABLE && CFG_TUH_DWC2_DMA_ENABLE) +#if CFG_TUD_MEM_DCACHE_ENABLE || CFG_TUH_MEM_DCACHE_ENABLE typedef struct { diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index 6b48c2346..257fa2833 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -141,7 +141,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool dma_host_enabled(const dwc2_regs_t* dwc return CFG_TUH_DWC2_DMA_ENABLE && ghwcfg2.arch == GHWCFG2_ARCH_INTERNAL_DMA; } -#if CFG_TUH_MEM_DCACHE_ENABLE && CFG_TUH_DWC2_DMA_ENABLE +#if CFG_TUH_MEM_DCACHE_ENABLE bool hcd_dcache_clean(const void* addr, uint32_t data_size) { TU_VERIFY(addr && data_size); return dwc2_dcache_clean(addr, data_size); diff --git a/src/tusb_option.h b/src/tusb_option.h index b8a4059a8..867babc33 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -465,13 +465,6 @@ #define CFG_TUD_MEM_DCACHE_LINE_SIZE CFG_TUSB_MEM_DCACHE_LINE_SIZE #endif -#if CFG_TUD_MEM_DCACHE_ENABLE && \ - (CFG_TUD_DWC2_DMA_ENABLE || defined(TUP_USBIP_CHIPIDEA_HS)) - #define TUD_EPBUF_DCACHE_ALIGNED 1 -#else - #define TUD_EPBUF_DCACHE_ALIGNED 0 -#endif - #ifndef CFG_TUD_ENDPOINT0_SIZE #define CFG_TUD_ENDPOINT0_SIZE 64 #endif @@ -591,13 +584,6 @@ #define CFG_TUH_MEM_DCACHE_LINE_SIZE CFG_TUSB_MEM_DCACHE_LINE_SIZE #endif -#if CFG_TUH_MEM_DCACHE_ENABLE && \ - (CFG_TUH_DWC2_DMA_ENABLE || defined(TUP_USBIP_CHIPIDEA_HS)) - #define TUH_EPBUF_DCACHE_ALIGNED 1 -#else - #define TUH_EPBUF_DCACHE_ALIGNED 0 -#endif - //------------- CLASS -------------// #ifndef CFG_TUH_HUB From ff18dbd2382d0e24e10cbf4e3f5d7a4feb9d3ce7 Mon Sep 17 00:00:00 2001 From: raldone01 Date: Sat, 5 Jul 2025 19:42:44 +0200 Subject: [PATCH 265/382] Rewrite of the web_serial example website. Fixes: #2632 --- .../webusb_serial/website/application.js | 431 ++++++++++++++++++ .../device/webusb_serial/website/index.html | 67 +++ .../device/webusb_serial/website/serial.js | 124 +++++ .../device/webusb_serial/website/style.css | 188 ++++++++ 4 files changed, 810 insertions(+) create mode 100644 examples/device/webusb_serial/website/application.js create mode 100644 examples/device/webusb_serial/website/index.html create mode 100644 examples/device/webusb_serial/website/serial.js create mode 100644 examples/device/webusb_serial/website/style.css diff --git a/examples/device/webusb_serial/website/application.js b/examples/device/webusb_serial/website/application.js new file mode 100644 index 000000000..a94a96714 --- /dev/null +++ b/examples/device/webusb_serial/website/application.js @@ -0,0 +1,431 @@ +'use strict'; + +(() => { + const connectBtn = document.getElementById('connect'); + const resetAllBtn = document.getElementById('reset_all'); + const resetOutputBtn = document.getElementById('reset_output'); + const senderLines = document.getElementById('sender_lines'); + const receiverLines = document.getElementById('receiver_lines'); + const commandLine = document.getElementById('command_line'); + const status = document.getElementById('status'); + const newlineModeSelect = document.getElementById('newline_mode'); + const sendModeBtn = document.getElementById('send_mode'); + const autoReconnectCheckbox = document.getElementById('auto_reconnect'); + const forgetDeviceBtn = document.getElementById('forget_device'); + const forgetAllDevicesBtn = document.getElementById('forget_all_devices'); + + const nearTheBottomThreshold = 100; // pixels from the bottom to trigger scroll + + let port = null; + let lastPort = null; // for reconnecting and initial connection + + const history = []; + let historyIndex = -1; + let lastCommand = null; + let lastCommandCount = 0; + let lastCommandButton = null; + + let sendMode = 'command'; // default mode + + let reconnectIntervalId = null; // track reconnect interval + + // Format incoming data to string based on newline mode + const decodeData = (() => { + const decoder = new TextDecoder(); + return dataView => decoder.decode(dataView); + })(); + + // Normalize newline if mode is ANY + const normalizeNewlines = (text, mode) => { + switch (mode) { + case 'CR': + // Only \r: Replace all \n with \r + return text.replace(/\r?\n/g, '\r'); + case 'CRLF': + // Replace lone \r or \n with \r\n + return text.replace(/\r\n|[\r\n]/g, '\r\n'); + case 'ANY': + // Accept any \r, \n, \r\n. Normalize as \n for display + return text.replace(/\r\n|\r/g, '\n'); + default: + return text; + } + }; + + // Append line to container, optionally scroll to bottom + const appendLineToReceiver = (container, text, className = '') => { + const div = document.createElement('div'); + if (className) div.className = className; + div.textContent = text; + container.appendChild(div); + + const distanceFromBottom = container.scrollHeight - (container.scrollTop + container.clientHeight); + if (distanceFromBottom < nearTheBottomThreshold) { + requestAnimationFrame(() => { + div.scrollIntoView({ behavior: "instant" }); + }); + } + }; + + // Append sent command to sender container as a clickable element + const appendCommandToSender = (container, text) => { + if (text === lastCommand) { + // Increment count and update button + lastCommandCount++; + lastCommandButton.textContent = `${text} ×${lastCommandCount}`; + } else { + // Reset count and add new button + lastCommand = text; + lastCommandCount = 1; + + const commandEl = document.createElement('button'); + commandEl.className = 'sender-entry'; + commandEl.type = 'button'; + commandEl.textContent = text; + commandEl.addEventListener('click', () => { + commandLine.value = text; + commandLine.focus(); + }); + container.appendChild(commandEl); + lastCommandButton = commandEl; + + const distanceFromBottom = container.scrollHeight - (container.scrollTop + container.clientHeight); + if (distanceFromBottom < nearTheBottomThreshold) { + requestAnimationFrame(() => { + commandEl.scrollIntoView({ behavior: 'instant' }); + }); + } + } + }; + + // Update status text and style + const setStatus = (msg, level = 'info') => { + console.log(msg); + status.textContent = msg; + status.className = 'status status-' + level; + }; + + // Disconnect helper + const disconnectPort = async () => { + if (port) { + try { + await port.disconnect(); + } catch (error) { + setStatus(`Disconnect error: ${error.message}`, 'error'); + } + port = null; + connectBtn.textContent = 'Connect'; + commandLine.disabled = true; + } + }; + + // Connect helper + const connectPort = async (initial=false) => { + try { + let grantedDevices = await serial.getPorts(); + if (grantedDevices.length === 0 && initial) { + return false; + } + if (grantedDevices.length === 0) { + // No previously granted devices, request a new one + setStatus('Requesting device...', 'info'); + port = await serial.requestPort(); + } else { + if (lastPort) { + // Try to reconnect to the last used port + const matchingPort = grantedDevices.find(p => p.portPointToSameDevice(lastPort)); + if (matchingPort) { + port = matchingPort; + setStatus('Reconnecting to last device...', 'info'); + } else { + return false; + } + } else { + // No last port, just use the first available + port = grantedDevices[0]; + setStatus('Connecting to first device...', 'info'); + } + } + + await port.connect(); + lastPort = port; // save for reconnecting + + setStatus(`Connected to ${port.device.productName || 'device'}`, 'info'); + connectBtn.textContent = 'Disconnect'; + commandLine.disabled = false; + commandLine.focus(); + + port.onReceive = dataView => { + let text = decodeData(dataView); + text = normalizeNewlines(text, newlineModeSelect.value); + appendLineToReceiver(receiverLines, text, 'received'); + }; + + port.onReceiveError = error => { + setStatus(`Read error: ${error.message}`, 'error'); + // Start auto reconnect on error if enabled + tryAutoReconnect(); + }; + return true; + } catch (error) { + setStatus(`Connection failed: ${error.message}`, 'error'); + port = null; + connectBtn.textContent = 'Connect'; + commandLine.disabled = true; + return false; + } + }; + + // Start auto reconnect interval if checkbox is checked and not already running + const tryAutoReconnect = () => { + if (!autoReconnectCheckbox.checked) return; + if (reconnectIntervalId !== null) return; // already trying + setStatus('Attempting to auto-reconnect...', 'info'); + reconnectIntervalId = setInterval(async () => { + if (!autoReconnectCheckbox.checked) { + clearInterval(reconnectIntervalId); + reconnectIntervalId = null; + setStatus('Auto-reconnect stopped.', 'info'); + return; + } + await disconnectPort(); + const success = await connectPort(); + if (success) { + clearInterval(reconnectIntervalId); + reconnectIntervalId = null; + setStatus('Reconnected successfully.', 'info'); + } + }, 1000); + }; + + // Stop auto reconnect immediately + const stopAutoReconnect = () => { + if (reconnectIntervalId !== null) { + clearInterval(reconnectIntervalId); + reconnectIntervalId = null; + setStatus('Auto-reconnect stopped.', 'info'); + } + }; + + // Connect button click handler + connectBtn.addEventListener('click', async () => { + if (!serial.isWebUsbSupported()) { + setStatus('WebUSB not supported on this browser', 'error'); + return; + } + + if (port) { + // Disconnect + stopAutoReconnect(); + await disconnectPort(); + setStatus('Disconnected', 'info'); + return; + } + + stopAutoReconnect(); + try { + // Connect + const success = await connectPort(); + if (success) { + setStatus('Connected', 'info'); + } + } catch (error) { + setStatus(`Connection failed: ${error.message}`, 'error'); + port = null; + connectBtn.textContent = 'Connect'; + commandLine.disabled = true; + } + }); + + // Checkbox toggle stops auto reconnect if unchecked + autoReconnectCheckbox.addEventListener('change', () => { + if (!autoReconnectCheckbox.checked) { + stopAutoReconnect(); + } else { + // Start auto reconnect immediately if not connected + if (!port) { + tryAutoReconnect(); + } + } + }); + + sendModeBtn.addEventListener('click', () => { + if (sendMode === 'command') { + sendMode = 'instant'; + sendModeBtn.classList.remove('send-mode-command'); + sendModeBtn.classList.add('send-mode-instant'); + sendModeBtn.textContent = 'Instant mode'; + // In instant mode, we clear the command line + commandLine.value = ''; + } else { + sendMode = 'command'; + sendModeBtn.classList.remove('send-mode-instant'); + sendModeBtn.classList.add('send-mode-command'); + sendModeBtn.textContent = 'Command mode'; + } + }); + + // Send command line input on Enter + commandLine.addEventListener('keydown', async e => { + if (!port) return; + + // Instant mode: send key immediately including special keys like Backspace, arrows, enter, etc. + if (sendMode === 'instant') { + e.preventDefault(); + + // Ignore only pure modifier keys without text representation + if (e.key.length === 1 || + e.key === 'Enter' || + e.key === 'Backspace' || + e.key === 'Tab' || + e.key === 'Escape' || + e.key === 'Delete' ) { + + let sendText = ''; + switch (e.key) { + case 'Enter': + switch (newlineModeSelect.value) { + case 'CR': sendText = '\r'; break; + case 'CRLF': sendText = '\r\n'; break; + default: sendText = '\n'; break; + } + break; + case 'Backspace': + // Usually no straightforward char to send for Backspace, + // but often ASCII DEL '\x7F' or '\b' (0x08) is sent. + sendText = '\x08'; // backspace + break; + case 'Tab': + sendText = '\t'; + break; + case 'Escape': + // Ignore or send ESC control char if needed + sendText = '\x1B'; + break; + case 'Delete': + sendText = '\x7F'; // DEL char + break; + default: + sendText = e.key; + } + + const encoder = new TextEncoder(); + try { + await port.send(encoder.encode(sendText)); + } catch (error) { + setStatus(`Send error: ${error.message}`, 'error'); + tryAutoReconnect(); + } + } + + return; + } + + // Command mode: handle up/down arrow keys for history + if (e.key === 'ArrowUp' || e.key === 'ArrowDown') { + e.preventDefault(); + if (history.length === 0) return; + if (e.key === 'ArrowUp') { + if (historyIndex === -1) historyIndex = history.length - 1; + else if (historyIndex > 0) historyIndex--; + } else if (e.key === 'ArrowDown') { + if (historyIndex !== -1) historyIndex++; + if (historyIndex >= history.length) historyIndex = -1; + } + commandLine.value = historyIndex === -1 ? '' : history[historyIndex]; + return; + } + + if (e.key !== 'Enter' || !port) return; + e.preventDefault(); + const text = commandLine.value; + if (!text) return; + + // Add command to history, ignore duplicate consecutive + if (history.length === 0 || history[history.length - 1] !== text) { + history.push(text); + } + historyIndex = -1; + + // Convert to Uint8Array with newline based on config + let sendText = text; + switch (newlineModeSelect.value) { + case 'CR': + sendText += '\r'; + break; + case 'CRLF': + sendText += '\r\n'; + break; + case 'ANY': + sendText += '\n'; + break; + } + const encoder = new TextEncoder(); + const data = encoder.encode(sendText); + + try { + await port.send(data); + appendCommandToSender(senderLines, sendText.replace(/[\r\n]+$/, '')); + commandLine.value = ''; + } catch (error) { + setStatus(`Send error: ${error.message}`, 'error'); + tryAutoReconnect(); + } + }); + + // Forget device button clears stored device info + forgetDeviceBtn.addEventListener('click', async () => { + if (port) { + // Disconnect first + await port.disconnect(); + await port.forgetDevice(); + stopAutoReconnect(); + await disconnectPort(); + + setStatus('Device forgotten', 'info'); + } else { + setStatus('No device to forget', 'error'); + } + }); + + // Forget all devices button clears all stored device info + forgetAllDevicesBtn.addEventListener('click', async () => { + stopAutoReconnect(); + await disconnectPort(); + let ports = await serial.getPorts(); + if (ports.length > 0) { + for (const p of ports) { + await p.forgetDevice(); + } + setStatus('All devices forgotten', 'info'); + } else { + setStatus('No devices to forget', 'error'); + } + }); + + // Reset output button clears receiver + resetOutputBtn.addEventListener('click', () => { + receiverLines.innerHTML = ''; + }); + + // Reset button clears sender and receiver + resetAllBtn.addEventListener('click', () => { + senderLines.innerHTML = ''; + receiverLines.innerHTML = ''; + lastCommand = null; + lastCommandCount = 0; + lastCommandButton = null; + }); + + + // Disable input on load + commandLine.disabled = true; + + // Show warning if no WebUSB support + if (!serial.isWebUsbSupported()) { + setStatus('WebUSB not supported on this browser', 'error'); + } else { + // try to connect to any available device + connectPort(true); + } +})(); diff --git a/examples/device/webusb_serial/website/index.html b/examples/device/webusb_serial/website/index.html new file mode 100644 index 000000000..91d6e4fba --- /dev/null +++ b/examples/device/webusb_serial/website/index.html @@ -0,0 +1,67 @@ + + + + + + + TinyUSB WebUSB Serial + + + + + + +
+

TinyUSB - WebUSB Serial

+ + Find my source on GitHub + +
+
+
+ + + + + + + +
+
+ + Click "Connect" to start + +
+
+
+

Sender

+
+
+
+
+ + +
+
+
+

Receiver

+
+
+
+
+
+
+ + + diff --git a/examples/device/webusb_serial/website/serial.js b/examples/device/webusb_serial/website/serial.js new file mode 100644 index 000000000..2b60f2cc7 --- /dev/null +++ b/examples/device/webusb_serial/website/serial.js @@ -0,0 +1,124 @@ +'use strict'; + +const serial = { + isWebUsbSupported: () => 'usb' in navigator, + + // Returns array of connected devices wrapped as serial.Port instances + async getPorts() { + const devices = await navigator.usb.getDevices(); + return devices.map(device => new serial.Port(device)); + }, + + // Prompts user to select a device matching filters and wraps it in serial.Port + async requestPort() { + const filters = [ + { vendorId: 0xcafe }, // TinyUSB + { vendorId: 0x239a }, // Adafruit + { vendorId: 0x2e8a }, // Raspberry Pi + { vendorId: 0x303a }, // Espressif + { vendorId: 0x2341 }, // Arduino + ]; + const device = await navigator.usb.requestDevice({ filters }); + return new serial.Port(device); + }, + + Port: class { + constructor(device) { + this.device = device; + this.interfaceNumber = 0; + this.endpointIn = 0; + this.endpointOut = 0; + this.readLoopActive = false; + } + + portPointToSameDevice(port) { + if (this.device.vendorId !== port.device.vendorId) return false; + if (this.device.productId !== port.device.productId) return false; + if (this.device.serialNumber !== port.device.serialNumber) return false; + return true; + } + + // Connect and start reading loop + async connect() { + await this.device.open(); + + if (!this.device.configuration) { + await this.device.selectConfiguration(1); + } + + // Find interface with vendor-specific class (0xFF) and endpoints + for (const iface of this.device.configuration.interfaces) { + for (const alternate of iface.alternates) { + if (alternate.interfaceClass === 0xff) { + this.interfaceNumber = iface.interfaceNumber; + for (const endpoint of alternate.endpoints) { + if (endpoint.direction === 'out') this.endpointOut = endpoint.endpointNumber; + else if (endpoint.direction === 'in') this.endpointIn = endpoint.endpointNumber; + } + } + } + } + + if (this.interfaceNumber === undefined) { + throw new Error('No suitable interface found.'); + } + + await this.device.claimInterface(this.interfaceNumber); + await this.device.selectAlternateInterface(this.interfaceNumber, 0); + + // Set device to ENABLE (0x22 = SET_CONTROL_LINE_STATE, value 0x01 = activate) + await this.device.controlTransferOut({ + requestType: 'class', + recipient: 'interface', + request: 0x22, + value: 0x01, + index: this.interfaceNumber, + }); + + this.readLoopActive = true; + this._readLoop(); + } + + // Internal continuous read loop + async _readLoop() { + while (this.readLoopActive) { + try { + const result = await this.device.transferIn(this.endpointIn, 64); + if (result.data && this.onReceive) { + this.onReceive(result.data); + } + } catch (error) { + this.readLoopActive = false; + if (this.onReceiveError) { + this.onReceiveError(error); + } + } + } + } + + // Stop reading and release device + async disconnect() { + this.readLoopActive = false; + await this.device.controlTransferOut({ + requestType: 'class', + recipient: 'interface', + request: 0x22, + value: 0x00, + index: this.interfaceNumber, + }); + await this.device.close(); + } + + // Send data to device + send(data) { + return this.device.transferOut(this.endpointOut, data); + } + + async forgetDevice() { + if (this.device.opened) { + await this.device.close(); + } + await this.device.forget(); + } + } +}; diff --git a/examples/device/webusb_serial/website/style.css b/examples/device/webusb_serial/website/style.css new file mode 100644 index 000000000..b73735d13 --- /dev/null +++ b/examples/device/webusb_serial/website/style.css @@ -0,0 +1,188 @@ +/* Reset default margins and make html, body full height */ +html, +body { + height: 100%; + margin: 0; + font-family: sans-serif; + background: #f5f5f5; + color: #333; +} + +body { + display: flex; + flex-direction: column; + height: 100vh; +} + +/* Header row styling */ +.header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.5em 1em; + flex-shrink: 0; +} + +h1, h2 { + margin: 0; +} + +.github-link { + font-weight: 600; +} + +/* Main is flex column */ +main { + display: flex; + flex-direction: column; + flex: 1; + width: 100%; +} + +/* Controls top row in main*/ +.controls-section, .status-section { + padding: 1rem; + flex-shrink: 0; +} + +/* Container for the two columns */ +.io-container { + display: flex; + flex: 1; + /* fill remaining vertical space */ + width: 100%; +} + +/* Both columns flex equally and full height */ +.column { + flex: 1; + padding: 1rem; + overflow: auto; + display: flex; + flex-direction: column; +} + +.sender { + display: flex; + flex-direction: column; +} + +.sender-entry { + width: 100%; + display: flex; + flex-direction: row; + align-items: center; + background: none; + border: none; + border-bottom: 1px solid #ccc; + /* light gray line */ + padding: 0.5rem 1rem; + margin: 0; + gap: 0; + text-align: left; + cursor: pointer; + font-size: 1rem; + color: inherit; +} + +.sender-entry:hover { + background-color: #f0f0f0; +} + +.monospaced { + font-family: 'Courier New', Courier, monospace; + font-size: 1rem; + color: #333; +} + +.scrollbox-wrapper { + position: relative; + padding: 0.5rem; + flex: 1; + + display: block; + overflow: hidden; +} + +.scrollbox { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + overflow-y: auto; + overflow-x: auto; + margin-top: 0.5rem; + margin-bottom: 0.5rem; + background-color: #fff; + border-radius: 0.5rem; + white-space: nowrap; +} + +.send-container { + display: flex; + flex-direction: row; + gap: 0.5rem; +} + +.send-mode-command { + background-color: light-gray; +} + +.send-mode-instant { + background-color: blue; +} + +/* UI Styles */ +.controls { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 1rem; + flex: 1 +} + +.btn { + padding: 0.5rem 1rem; + font-size: 1rem; + border: none; + border-radius: 0.3rem; + cursor: pointer; +} + +.good { + background-color: #2ecc71; + /* green */ + color: #fff; +} + +.danger { + background-color: #e74c3c; + /* red */ + color: #fff; +} + +.input { + width: 100%; + padding: 12px 16px; + font-size: 1rem; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + border: 2px solid #ddd; + border-radius: 8px; + background-color: #fafafa; + color: #333; + transition: border-color 0.3s ease, box-shadow 0.3s ease; + outline: none; + box-sizing: border-box; +} + +.input::placeholder { + color: #aaa; + font-style: italic; +} + +.input:focus { + border-color: #0078d7; + box-shadow: 0 0 6px rgba(0, 120, 215, 0.5); + background-color: #fff; +} From 98b975202ced1940e642796f28a868e96dc492cc Mon Sep 17 00:00:00 2001 From: raldone01 Date: Sat, 5 Jul 2025 19:42:44 +0200 Subject: [PATCH 266/382] Minor bug fixes. Persist settings. --- .../webusb_serial/website/application.js | 146 +++++++++++------- .../device/webusb_serial/website/index.html | 2 +- 2 files changed, 94 insertions(+), 54 deletions(-) diff --git a/examples/device/webusb_serial/website/application.js b/examples/device/webusb_serial/website/application.js index a94a96714..8c01ce111 100644 --- a/examples/device/webusb_serial/website/application.js +++ b/examples/device/webusb_serial/website/application.js @@ -25,47 +25,10 @@ let lastCommandCount = 0; let lastCommandButton = null; - let sendMode = 'command'; // default mode + let sendMode = localStorage.getItem('sendMode') || 'command'; - let reconnectIntervalId = null; // track reconnect interval - - // Format incoming data to string based on newline mode - const decodeData = (() => { - const decoder = new TextDecoder(); - return dataView => decoder.decode(dataView); - })(); - - // Normalize newline if mode is ANY - const normalizeNewlines = (text, mode) => { - switch (mode) { - case 'CR': - // Only \r: Replace all \n with \r - return text.replace(/\r?\n/g, '\r'); - case 'CRLF': - // Replace lone \r or \n with \r\n - return text.replace(/\r\n|[\r\n]/g, '\r\n'); - case 'ANY': - // Accept any \r, \n, \r\n. Normalize as \n for display - return text.replace(/\r\n|\r/g, '\n'); - default: - return text; - } - }; - - // Append line to container, optionally scroll to bottom - const appendLineToReceiver = (container, text, className = '') => { - const div = document.createElement('div'); - if (className) div.className = className; - div.textContent = text; - container.appendChild(div); - - const distanceFromBottom = container.scrollHeight - (container.scrollTop + container.clientHeight); - if (distanceFromBottom < nearTheBottomThreshold) { - requestAnimationFrame(() => { - div.scrollIntoView({ behavior: "instant" }); - }); - } - }; + // track reconnect interval + let reconnectIntervalId = null; // Append sent command to sender container as a clickable element const appendCommandToSender = (container, text) => { @@ -98,6 +61,55 @@ } }; + // Restore command history + history.push(...(JSON.parse(localStorage.getItem('commandHistory') || '[]'))); + for (const cmd of history) { + appendCommandToSender(senderLines, cmd); + } + + // Restore auto reconnect checkbox + autoReconnectCheckbox.checked = localStorage.getItem('autoReconnect') === 'true'; + // Restore newline mode + const savedNewlineMode = localStorage.getItem('newlineMode'); + if (savedNewlineMode) newlineModeSelect.value = savedNewlineMode; + + // Format incoming data + const decodeData = (() => { + const decoder = new TextDecoder(); + return dataView => decoder.decode(dataView); + })(); + + const normalizeNewlines = (text, mode) => { + switch (mode) { + case 'CR': + // Only \r: Replace all \n with \r + return text.replace(/\r?\n/g, '\r'); + case 'CRLF': + // Replace lone \r or \n with \r\n + return text.replace(/\r\n|[\r\n]/g, '\r\n'); + case 'ANY': + // Accept any \r, \n, \r\n. Normalize as \n for display + return text.replace(/\r\n|\r/g, '\n'); + default: + return text; + } + }; + + // Append line to container, optionally scroll to bottom + const appendLineToReceiver = (container, text, className = '') => { + const div = document.createElement('div'); + if (className) div.className = className; + div.textContent = text; + container.appendChild(div); + + const distanceFromBottom = container.scrollHeight - (container.scrollTop + container.clientHeight); + if (distanceFromBottom < nearTheBottomThreshold) { + requestAnimationFrame(() => { + div.scrollIntoView({ behavior: "instant" }); + }); + } + }; + // Update status text and style const setStatus = (msg, level = 'info') => { console.log(msg); @@ -120,7 +132,7 @@ }; // Connect helper - const connectPort = async (initial=false) => { + const connectPort = async (initial = false) => { try { let grantedDevices = await serial.getPorts(); if (grantedDevices.length === 0 && initial) { @@ -148,24 +160,27 @@ } await port.connect(); - lastPort = port; // save for reconnecting + // save for reconnecting + lastPort = port; setStatus(`Connected to ${port.device.productName || 'device'}`, 'info'); connectBtn.textContent = 'Disconnect'; commandLine.disabled = false; commandLine.focus(); + port.onReceiveError = async error => { + setStatus(`Read error: ${error.message}`, 'error'); + await disconnectPort(); + // Start auto reconnect on error if enabled + await tryAutoReconnect(); + }; + port.onReceive = dataView => { let text = decodeData(dataView); text = normalizeNewlines(text, newlineModeSelect.value); appendLineToReceiver(receiverLines, text, 'received'); }; - port.onReceiveError = error => { - setStatus(`Read error: ${error.message}`, 'error'); - // Start auto reconnect on error if enabled - tryAutoReconnect(); - }; return true; } catch (error) { setStatus(`Connection failed: ${error.message}`, 'error'); @@ -177,7 +192,7 @@ }; // Start auto reconnect interval if checkbox is checked and not already running - const tryAutoReconnect = () => { + const tryAutoReconnect = async () => { if (!autoReconnectCheckbox.checked) return; if (reconnectIntervalId !== null) return; // already trying setStatus('Attempting to auto-reconnect...', 'info'); @@ -238,13 +253,16 @@ }); // Checkbox toggle stops auto reconnect if unchecked - autoReconnectCheckbox.addEventListener('change', () => { + autoReconnectCheckbox.addEventListener('change', async () => { + localStorage.setItem('autoReconnect', autoReconnectCheckbox.checked); if (!autoReconnectCheckbox.checked) { stopAutoReconnect(); } else { // Start auto reconnect immediately if not connected - if (!port) { - tryAutoReconnect(); + console.log(port); + console.log(lastPort); + if (!port && lastPort) { + await tryAutoReconnect(); } } }); @@ -263,8 +281,16 @@ sendModeBtn.classList.add('send-mode-command'); sendModeBtn.textContent = 'Command mode'; } + localStorage.setItem('sendMode', sendMode); }); + // Set initial sendMode button state + if (sendMode === 'instant') { + sendModeBtn.classList.remove('send-mode-command'); + sendModeBtn.classList.add('send-mode-instant'); + sendModeBtn.textContent = 'Instant mode'; + } + // Send command line input on Enter commandLine.addEventListener('keydown', async e => { if (!port) return; @@ -314,7 +340,8 @@ await port.send(encoder.encode(sendText)); } catch (error) { setStatus(`Send error: ${error.message}`, 'error'); - tryAutoReconnect(); + await disconnectPort(); + await tryAutoReconnect(); } } @@ -344,6 +371,7 @@ // Add command to history, ignore duplicate consecutive if (history.length === 0 || history[history.length - 1] !== text) { history.push(text); + localStorage.setItem('commandHistory', JSON.stringify(history)); } historyIndex = -1; @@ -369,10 +397,15 @@ commandLine.value = ''; } catch (error) { setStatus(`Send error: ${error.message}`, 'error'); - tryAutoReconnect(); + await disconnectPort(); + await tryAutoReconnect(); } }); + newlineModeSelect.addEventListener('change', () => { + localStorage.setItem('newlineMode', newlineModeSelect.value); + }); + // Forget device button clears stored device info forgetDeviceBtn.addEventListener('click', async () => { if (port) { @@ -415,6 +448,13 @@ lastCommand = null; lastCommandCount = 0; lastCommandButton = null; + history.length = 0; + historyIndex = -1; + + // iterate and delete localStorage items + for (const key in localStorage) { + localStorage.removeItem(key); + } }); diff --git a/examples/device/webusb_serial/website/index.html b/examples/device/webusb_serial/website/index.html index 91d6e4fba..8d18ff8cf 100644 --- a/examples/device/webusb_serial/website/index.html +++ b/examples/device/webusb_serial/website/index.html @@ -50,7 +50,7 @@
- +
From d3f7dff180507161d0277617edbf423792a6b21e Mon Sep 17 00:00:00 2001 From: raldone01 Date: Sat, 5 Jul 2025 19:42:44 +0200 Subject: [PATCH 267/382] Major overhaul and logic cleanup. Adds support for web serial as well. --- .../webusb_serial/website/application.js | 881 +++++++++--------- .../device/webusb_serial/website/divider.js | 38 + .../device/webusb_serial/website/index.html | 37 +- .../device/webusb_serial/website/serial.js | 342 ++++--- .../device/webusb_serial/website/style.css | 25 +- 5 files changed, 769 insertions(+), 554 deletions(-) create mode 100644 examples/device/webusb_serial/website/divider.js diff --git a/examples/device/webusb_serial/website/application.js b/examples/device/webusb_serial/website/application.js index 8c01ce111..9e28c0204 100644 --- a/examples/device/webusb_serial/website/application.js +++ b/examples/device/webusb_serial/website/application.js @@ -1,471 +1,512 @@ 'use strict'; -(() => { - const connectBtn = document.getElementById('connect'); - const resetAllBtn = document.getElementById('reset_all'); - const resetOutputBtn = document.getElementById('reset_output'); - const senderLines = document.getElementById('sender_lines'); - const receiverLines = document.getElementById('receiver_lines'); - const commandLine = document.getElementById('command_line'); - const status = document.getElementById('status'); - const newlineModeSelect = document.getElementById('newline_mode'); - const sendModeBtn = document.getElementById('send_mode'); - const autoReconnectCheckbox = document.getElementById('auto_reconnect'); - const forgetDeviceBtn = document.getElementById('forget_device'); - const forgetAllDevicesBtn = document.getElementById('forget_all_devices'); +(async () => { + // bind to the html + const connectWebUsbSerialBtn = document.getElementById('connect_webusb_serial_btn'); + const connectSerialBtn = document.getElementById('connect_serial_btn'); + const disconnectBtn = document.getElementById('disconnect_btn'); + + const newlineModeSelect = document.getElementById('newline_mode_select'); + const autoReconnectCheckbox = document.getElementById('auto_reconnect_checkbox'); + const forgetDeviceBtn = document.getElementById('forget_device_btn'); + const forgetAllDevicesBtn = document.getElementById('forget_all_devices_btn'); + const resetAllBtn = document.getElementById('reset_all_btn'); + const resetOutputBtn = document.getElementById('reset_output_btn'); + const copyOutputBtn = document.getElementById('copy_output_btn'); + + const statusSpan = document.getElementById('status_span'); + + const commandHistoryScrollbox = document.getElementById('command_history_scrollbox'); + const commandLineInput = document.getElementById('command_line_input'); + const sendModeBtn = document.getElementById('send_mode_btn'); + + const receivedDataScrollbox = document.getElementById('received_data_scrollbox'); const nearTheBottomThreshold = 100; // pixels from the bottom to trigger scroll - let port = null; - let lastPort = null; // for reconnecting and initial connection + class Application { + constructor() { + this.currentPort = null; + this.textEncoder = new TextEncoder(); + this.textDecoder = new TextDecoder(); - const history = []; - let historyIndex = -1; - let lastCommand = null; - let lastCommandCount = 0; - let lastCommandButton = null; + this.reconnectTimeoutId = null; - let sendMode = localStorage.getItem('sendMode') || 'command'; + this.commandHistory = []; + this.commandHistoryIndex = -1; + this.lastCommandCount = 0; + this.lastCommand = null; + this.lastCommandBtn = null; - // track reconnect interval - let reconnectIntervalId = null; + // bind the UI elements + connectWebUsbSerialBtn.addEventListener('click', () => this.connectWebUsbSerialPort()); + connectSerialBtn.addEventListener('click', () => this.connectSerialPort()); + disconnectBtn.addEventListener('click', () => this.disconnectPort()); + newlineModeSelect.addEventListener('change', () => this.setNewlineMode()); + autoReconnectCheckbox.addEventListener('change', () => this.autoReconnectChanged()); + forgetDeviceBtn.addEventListener('click', () => this.forgetPort()); + forgetAllDevicesBtn.addEventListener('click', () => this.forgetAllPorts()); + resetAllBtn.addEventListener('click', () => this.resetAll()); + resetOutputBtn.addEventListener('click', () => this.resetOutput()); + copyOutputBtn.addEventListener('click', () => this.copyOutput()); + commandLineInput.addEventListener('keydown', (e) => this.handleCommandLineInput(e)); + sendModeBtn.addEventListener('click', () => this.toggleSendMode()); - // Append sent command to sender container as a clickable element - const appendCommandToSender = (container, text) => { - if (text === lastCommand) { - // Increment count and update button - lastCommandCount++; - lastCommandButton.textContent = `${text} ×${lastCommandCount}`; - } else { - // Reset count and add new button - lastCommand = text; - lastCommandCount = 1; + // restore state from localStorage - const commandEl = document.createElement('button'); - commandEl.className = 'sender-entry'; - commandEl.type = 'button'; - commandEl.textContent = text; - commandEl.addEventListener('click', () => { - commandLine.value = text; - commandLine.focus(); - }); - container.appendChild(commandEl); - lastCommandButton = commandEl; + // Restore command history + let savedCommandHistory = JSON.parse(localStorage.getItem('commandHistory') || '[]'); + for (const cmd of savedCommandHistory) { + this.appendCommandToHistory(cmd); + } - const distanceFromBottom = container.scrollHeight - (container.scrollTop + container.clientHeight); + this.sendMode = localStorage.getItem('sendMode') || 'command'; + this.setSendMode(this.sendMode); + + autoReconnectCheckbox.checked = localStorage.getItem('autoReconnect') === 'true'; + + let savedNewlineMode = localStorage.getItem('newlineMode'); + if (savedNewlineMode) { + newlineModeSelect.value = savedNewlineMode; + } + + this.connectWebUsbSerialPort(true); + } + + appendCommandToHistory(text) { + if (text === this.lastCommand) { + // Increment count and update button + this.lastCommandCount++; + this.lastCommandBtn.textContent = `${text} ×${this.lastCommandCount}`; + } else { + // Add a new entry to the command history + this.commandHistory.push(text); + localStorage.setItem('commandHistory', JSON.stringify(this.commandHistory)); + this.commandHistoryIndex = -1; + + const commandHistoryEntryBtn = document.createElement('button'); + commandHistoryEntryBtn.className = 'command-history-entry'; + commandHistoryEntryBtn.type = 'button'; + commandHistoryEntryBtn.textContent = text; + commandHistoryEntryBtn.addEventListener('click', () => { + if (commandLineInput.disabled) return; + commandLineInput.value = text; + commandLineInput.focus(); + }); + commandHistoryScrollbox.appendChild(commandHistoryEntryBtn); + + this.lastCommand = text; + this.lastCommandBtn = commandHistoryEntryBtn; + + // Scroll to the new entry if near the bottom + const distanceFromBottom = commandHistoryScrollbox.scrollHeight - (commandHistoryScrollbox.scrollTop + commandHistoryScrollbox.clientHeight); + if (distanceFromBottom < nearTheBottomThreshold) { + requestAnimationFrame(() => { + commandHistoryEntryBtn.scrollIntoView({ behavior: 'instant' }); + }); + } + } + } + + appendLineToReceived(text) { + const div = document.createElement('div'); + div.textContent = text; + receivedDataScrollbox.appendChild(div); + + // Scroll to the new entry if near the bottom + const distanceFromBottom = receivedDataScrollbox.scrollHeight - (receivedDataScrollbox.scrollTop + receivedDataScrollbox.clientHeight); if (distanceFromBottom < nearTheBottomThreshold) { requestAnimationFrame(() => { - commandEl.scrollIntoView({ behavior: 'instant' }); + div.scrollIntoView({ behavior: 'instant' }); }); } } - }; - // Restore command history - history.push(...(JSON.parse(localStorage.getItem('commandHistory') || '[]'))); - for (const cmd of history) { - appendCommandToSender(senderLines, cmd); - } - - // Restore auto reconnect checkbox - autoReconnectCheckbox.checked = localStorage.getItem('autoReconnect') === 'true'; - // Restore newline mode - const savedNewlineMode = localStorage.getItem('newlineMode'); - if (savedNewlineMode) newlineModeSelect.value = savedNewlineMode; - - // Format incoming data - const decodeData = (() => { - const decoder = new TextDecoder(); - return dataView => decoder.decode(dataView); - })(); - - const normalizeNewlines = (text, mode) => { - switch (mode) { - case 'CR': - // Only \r: Replace all \n with \r - return text.replace(/\r?\n/g, '\r'); - case 'CRLF': - // Replace lone \r or \n with \r\n - return text.replace(/\r\n|[\r\n]/g, '\r\n'); - case 'ANY': - // Accept any \r, \n, \r\n. Normalize as \n for display - return text.replace(/\r\n|\r/g, '\n'); - default: - return text; + setStatus(msg, level = 'info') { + console.log(msg); + statusSpan.textContent = msg; + statusSpan.className = 'status status-' + level; } - }; - // Append line to container, optionally scroll to bottom - const appendLineToReceiver = (container, text, className = '') => { - const div = document.createElement('div'); - if (className) div.className = className; - div.textContent = text; - container.appendChild(div); - - const distanceFromBottom = container.scrollHeight - (container.scrollTop + container.clientHeight); - if (distanceFromBottom < nearTheBottomThreshold) { - requestAnimationFrame(() => { - div.scrollIntoView({ behavior: "instant" }); - }); - } - }; - - // Update status text and style - const setStatus = (msg, level = 'info') => { - console.log(msg); - status.textContent = msg; - status.className = 'status status-' + level; - }; - - // Disconnect helper - const disconnectPort = async () => { - if (port) { - try { - await port.disconnect(); - } catch (error) { - setStatus(`Disconnect error: ${error.message}`, 'error'); - } - port = null; - connectBtn.textContent = 'Connect'; - commandLine.disabled = true; - } - }; - - // Connect helper - const connectPort = async (initial = false) => { - try { - let grantedDevices = await serial.getPorts(); - if (grantedDevices.length === 0 && initial) { - return false; - } - if (grantedDevices.length === 0) { - // No previously granted devices, request a new one - setStatus('Requesting device...', 'info'); - port = await serial.requestPort(); + updateUIConnectionState() { + if (this.currentPort && this.currentPort.isConnected) { + connectWebUsbSerialBtn.style.display = 'none'; + connectSerialBtn.style.display = 'none'; + disconnectBtn.style.display = 'block'; + commandLineInput.disabled = false; + commandLineInput.focus(); } else { - if (lastPort) { - // Try to reconnect to the last used port - const matchingPort = grantedDevices.find(p => p.portPointToSameDevice(lastPort)); - if (matchingPort) { - port = matchingPort; - setStatus('Reconnecting to last device...', 'info'); - } else { - return false; - } - } else { - // No last port, just use the first available - port = grantedDevices[0]; - setStatus('Connecting to first device...', 'info'); + if (serial.isWebUsbSupported()) { + connectWebUsbSerialBtn.style.display = 'block'; } + if (serial.isWebSerialSupported()) { + connectSerialBtn.style.display = 'block'; + } + if (!serial.isWebUsbSupported() && !serial.isWebSerialSupported()) { + this.setStatus('Your browser does not support WebUSB or WebSerial', 'error'); + } + disconnectBtn.style.display = 'none'; + commandLineInput.disabled = true; + commandLineInput.value = ''; + commandLineInput.blur(); + } + } + + async disconnectPort() { + this.stopAutoReconnect(); + if (!this.currentPort) return; + + try { + await this.currentPort.disconnect(); + } + catch (error) { + this.setStatus(`Disconnect error: ${error.message}`, 'error'); } - await port.connect(); - // save for reconnecting - lastPort = port; - - setStatus(`Connected to ${port.device.productName || 'device'}`, 'info'); - connectBtn.textContent = 'Disconnect'; - commandLine.disabled = false; - commandLine.focus(); - - port.onReceiveError = async error => { - setStatus(`Read error: ${error.message}`, 'error'); - await disconnectPort(); - // Start auto reconnect on error if enabled - await tryAutoReconnect(); - }; - - port.onReceive = dataView => { - let text = decodeData(dataView); - text = normalizeNewlines(text, newlineModeSelect.value); - appendLineToReceiver(receiverLines, text, 'received'); - }; - - return true; - } catch (error) { - setStatus(`Connection failed: ${error.message}`, 'error'); - port = null; - connectBtn.textContent = 'Connect'; - commandLine.disabled = true; - return false; + this.updateUIConnectionState(); } - }; - // Start auto reconnect interval if checkbox is checked and not already running - const tryAutoReconnect = async () => { - if (!autoReconnectCheckbox.checked) return; - if (reconnectIntervalId !== null) return; // already trying - setStatus('Attempting to auto-reconnect...', 'info'); - reconnectIntervalId = setInterval(async () => { - if (!autoReconnectCheckbox.checked) { - clearInterval(reconnectIntervalId); - reconnectIntervalId = null; - setStatus('Auto-reconnect stopped.', 'info'); + async onReceive(dataView) { + this.updateUIConnectionState(); + let text = this.textDecoder.decode(dataView); + text = this.normalizeNewlines(text); + this.appendLineToReceived(text); + } + + async onReceiveError(error) { + this.setStatus(`Read error: ${error.message}`, 'error'); + await this.disconnectPort(); + // Start auto reconnect on error if enabled + this.tryAutoReconnect(); + } + + async connectSerialPort() { + if (!serial.isWebSerialSupported()) { + this.setStatus('Serial not supported on this browser', 'error'); return; } - await disconnectPort(); - const success = await connectPort(); - if (success) { - clearInterval(reconnectIntervalId); - reconnectIntervalId = null; - setStatus('Reconnected successfully.', 'info'); - } - }, 1000); - }; - - // Stop auto reconnect immediately - const stopAutoReconnect = () => { - if (reconnectIntervalId !== null) { - clearInterval(reconnectIntervalId); - reconnectIntervalId = null; - setStatus('Auto-reconnect stopped.', 'info'); - } - }; - - // Connect button click handler - connectBtn.addEventListener('click', async () => { - if (!serial.isWebUsbSupported()) { - setStatus('WebUSB not supported on this browser', 'error'); - return; - } - - if (port) { - // Disconnect - stopAutoReconnect(); - await disconnectPort(); - setStatus('Disconnected', 'info'); - return; - } - - stopAutoReconnect(); - try { - // Connect - const success = await connectPort(); - if (success) { - setStatus('Connected', 'info'); - } - } catch (error) { - setStatus(`Connection failed: ${error.message}`, 'error'); - port = null; - connectBtn.textContent = 'Connect'; - commandLine.disabled = true; - } - }); - - // Checkbox toggle stops auto reconnect if unchecked - autoReconnectCheckbox.addEventListener('change', async () => { - localStorage.setItem('autoReconnect', autoReconnectCheckbox.checked); - if (!autoReconnectCheckbox.checked) { - stopAutoReconnect(); - } else { - // Start auto reconnect immediately if not connected - console.log(port); - console.log(lastPort); - if (!port && lastPort) { - await tryAutoReconnect(); + try { + this.setStatus('Requesting device...', 'info'); + this.currentPort = await serial.requestSerialPort(); + this.currentPort.onReceiveError = error => this.onReceiveError(error); + this.currentPort.onReceive = dataView => this.onReceive(dataView); + await this.currentPort.connect(); + this.setStatus('Connected', 'info'); + } catch (error) { + this.setStatus(`Connection failed: ${error.message}`, 'error'); + if (this.currentPort) { + await this.currentPort.forgetDevice(); + this.currentPort = null; + } } } - }); - sendModeBtn.addEventListener('click', () => { - if (sendMode === 'command') { - sendMode = 'instant'; - sendModeBtn.classList.remove('send-mode-command'); - sendModeBtn.classList.add('send-mode-instant'); - sendModeBtn.textContent = 'Instant mode'; - // In instant mode, we clear the command line - commandLine.value = ''; - } else { - sendMode = 'command'; - sendModeBtn.classList.remove('send-mode-instant'); - sendModeBtn.classList.add('send-mode-command'); - sendModeBtn.textContent = 'Command mode'; - } - localStorage.setItem('sendMode', sendMode); - }); + async connectWebUsbSerialPort(initial = false) { + if (!serial.isWebUsbSupported()) { + this.setStatus('WebUSB not supported on this browser', 'error'); + return; + } + try { + let first_time_connection = false; + let grantedDevices = await serial.getWebUsbSerialPorts(); + if (initial) { + if (!autoReconnectCheckbox.checked || grantedDevices.length === 0) { + return false; + } - // Set initial sendMode button state - if (sendMode === 'instant') { - sendModeBtn.classList.remove('send-mode-command'); - sendModeBtn.classList.add('send-mode-instant'); - sendModeBtn.textContent = 'Instant mode'; - } - - // Send command line input on Enter - commandLine.addEventListener('keydown', async e => { - if (!port) return; - - // Instant mode: send key immediately including special keys like Backspace, arrows, enter, etc. - if (sendMode === 'instant') { - e.preventDefault(); - - // Ignore only pure modifier keys without text representation - if (e.key.length === 1 || - e.key === 'Enter' || - e.key === 'Backspace' || - e.key === 'Tab' || - e.key === 'Escape' || - e.key === 'Delete' ) { - - let sendText = ''; - switch (e.key) { - case 'Enter': - switch (newlineModeSelect.value) { - case 'CR': sendText = '\r'; break; - case 'CRLF': sendText = '\r\n'; break; - default: sendText = '\n'; break; + // Connect to the device that was saved to localStorage otherwise use the first one + const savedPortInfo = JSON.parse(localStorage.getItem('webUSBSerialPort')); + if (savedPortInfo) { + for (const device of grantedDevices) { + if (device.device.vendorId === savedPortInfo.vendorId && device.device.productId === savedPortInfo.productId) { + this.currentPort = device; + break; + } } - break; - case 'Backspace': - // Usually no straightforward char to send for Backspace, - // but often ASCII DEL '\x7F' or '\b' (0x08) is sent. - sendText = '\x08'; // backspace - break; - case 'Tab': - sendText = '\t'; - break; - case 'Escape': - // Ignore or send ESC control char if needed - sendText = '\x1B'; - break; - case 'Delete': - sendText = '\x7F'; // DEL char - break; - default: - sendText = e.key; + } + if (!this.currentPort) { + this.currentPort = grantedDevices[0]; + } + + this.setStatus('Connecting to first device...', 'info'); + } else { + // Prompt the user to select a device + this.setStatus('Requesting device...', 'info'); + this.currentPort = await serial.requestWebUsbSerialPort(); + first_time_connection = true; } - const encoder = new TextEncoder(); + this.currentPort.onReceiveError = error => this.onReceiveError(error); + this.currentPort.onReceive = dataView => this.onReceive(dataView); + try { - await port.send(encoder.encode(sendText)); + await this.currentPort.connect(); + + // save the port to localStorage + const portInfo = { + vendorId: this.currentPort.device.vendorId, + productId: this.currentPort.device.productId, + } + localStorage.setItem('webUSBSerialPort', JSON.stringify(portInfo)); + + this.setStatus('Connected', 'info'); } catch (error) { - setStatus(`Send error: ${error.message}`, 'error'); - await disconnectPort(); - await tryAutoReconnect(); + if (first_time_connection) { + // Forget the device if a first time connection fails + await this.currentPort.forgetDevice(); + this.currentPort = null; + } + throw error; + } + + this.updateUIConnectionState(); + } catch (error) { + this.setStatus(`Connection failed: ${error.message}`, 'error'); + } + } + + async reconnectPort() { + if (this.currentPort) { + this.setStatus('Reconnecting...', 'info'); + try { + await this.currentPort.connect(); + this.setStatus('Reconnected', 'info'); + } catch (error) { + this.setStatus(`Reconnect failed: ${error.message}`, 'error'); } } - - return; + this.updateUIConnectionState(); } - // Command mode: handle up/down arrow keys for history - if (e.key === 'ArrowUp' || e.key === 'ArrowDown') { + async forgetPort() { + this.stopAutoReconnect(); + if (this.currentPort) { + await this.currentPort.forgetDevice(); + this.currentPort = null; + this.setStatus('Device forgotten', 'info'); + } else { + this.setStatus('No device to forget', 'error'); + } + this.updateUIConnectionState(); + } + + async forgetAllPorts() { + this.stopAutoReconnect(); + await this.forgetPort(); + if (serial.isWebUsbSupported()) { + let ports = await serial.getWebUsbSerialPorts(); + for (const p of ports) { + await p.forgetDevice(); + } + } + this.updateUIConnectionState(); + } + + setNewlineMode() { + localStorage.setItem('newlineMode', newlineModeSelect.value); + } + + autoReconnectChanged() { + if (autoReconnectCheckbox.checked) { + this.setStatus('Auto-reconnect enabled', 'info'); + this.tryAutoReconnect(); + } else { + this.setStatus('Auto-reconnect disabled', 'info'); + this.stopAutoReconnect(); + } + localStorage.setItem('autoReconnect', autoReconnectCheckbox.checked); + } + + stopAutoReconnect() { + if (this.reconnectTimeoutId !== null) { + clearTimeout(this.reconnectTimeoutId); + this.reconnectTimeoutId = null; + this.setStatus('Auto-reconnect stopped.', 'info'); + } + } + + tryAutoReconnect() { + this.updateUIConnectionState(); + if (!autoReconnectCheckbox.checked) return; + if (this.reconnectTimeoutId !== null) return; // already trying + this.setStatus('Attempting to auto-reconnect...', 'info'); + this.reconnectTimeoutId = setTimeout(async () => { + this.reconnectTimeoutId = null; + if (!autoReconnectCheckbox.checked) { + this.setStatus('Auto-reconnect stopped.', 'info'); + return; + } + if (this.currentPort) { + try { + await this.currentPort.connect(); + } finally { + this.updateUIConnectionState(); + } + } + }, 1000); + } + + async handleCommandLineInput(e) { + // Instant mode: send key immediately including special keys like Backspace, arrows, enter, etc. + if (this.sendMode === 'instant') { + e.preventDefault(); + + // Ignore only pure modifier keys without text representation + if (e.key.length === 1 || + e.key === 'Enter' || + e.key === 'Backspace' || + e.key === 'Tab' || + e.key === 'Escape' || + e.key === 'Delete' ) { + + let sendText = ''; + switch (e.key) { + case 'Enter': + switch (newlineModeSelect.value) { + case 'CR': sendText = '\r'; break; + case 'CRLF': sendText = '\r\n'; break; + default: sendText = '\n'; break; + } + break; + case 'Backspace': + // Usually no straightforward char to send for Backspace, + // but often ASCII DEL '\x7F' or '\b' (0x08) is sent. + sendText = '\x08'; // backspace + break; + case 'Tab': + sendText = '\t'; + break; + case 'Escape': + // Ignore or send ESC control char if needed + sendText = '\x1B'; + break; + case 'Delete': + sendText = '\x7F'; // DEL char + break; + default: + sendText = e.key; + } + try { + await port.send(this.textEncoder.encode(sendText)); + } catch (error) { + this.setStatus(`Send error: ${error.message}`, 'error'); + this.tryAutoReconnect(); + } + } + + return; + } + + // Command mode: handle up/down arrow keys for history + if (e.key === 'ArrowUp' || e.key === 'ArrowDown') { + e.preventDefault(); + if (this.commandHistory.length === 0) return; + if (e.key === 'ArrowUp') { + if (this.commandHistoryIndex === -1) this.commandHistoryIndex = this.commandHistory.length - 1; + else if (this.commandHistoryIndex > 0) this.commandHistoryIndex--; + } else if (e.key === 'ArrowDown') { + if (this.commandHistoryIndex !== -1) this.commandHistoryIndex++; + if (this.commandHistoryIndex >= this.commandHistory.length) this.commandHistoryIndex = -1; + } + commandLineInput.value = this.commandHistoryIndex === -1 ? '' : this.commandHistory[this.commandHistoryIndex]; + return; + } + + if (e.key !== 'Enter' || !this.currentPort.isConnected) return; e.preventDefault(); - if (history.length === 0) return; - if (e.key === 'ArrowUp') { - if (historyIndex === -1) historyIndex = history.length - 1; - else if (historyIndex > 0) historyIndex--; - } else if (e.key === 'ArrowDown') { - if (historyIndex !== -1) historyIndex++; - if (historyIndex >= history.length) historyIndex = -1; + const text = commandLineInput.value; + if (!text) return; + + // Convert to Uint8Array with newline based on config + let sendText = text; + switch (newlineModeSelect.value) { + case 'CR': + sendText += '\r'; + break; + case 'CRLF': + sendText += '\r\n'; + break; + case 'ANY': + sendText += '\n'; + break; } - commandLine.value = historyIndex === -1 ? '' : history[historyIndex]; - return; - } + const data = this.textEncoder.encode(sendText); - if (e.key !== 'Enter' || !port) return; - e.preventDefault(); - const text = commandLine.value; - if (!text) return; - - // Add command to history, ignore duplicate consecutive - if (history.length === 0 || history[history.length - 1] !== text) { - history.push(text); - localStorage.setItem('commandHistory', JSON.stringify(history)); - } - historyIndex = -1; - - // Convert to Uint8Array with newline based on config - let sendText = text; - switch (newlineModeSelect.value) { - case 'CR': - sendText += '\r'; - break; - case 'CRLF': - sendText += '\r\n'; - break; - case 'ANY': - sendText += '\n'; - break; - } - const encoder = new TextEncoder(); - const data = encoder.encode(sendText); - - try { - await port.send(data); - appendCommandToSender(senderLines, sendText.replace(/[\r\n]+$/, '')); - commandLine.value = ''; - } catch (error) { - setStatus(`Send error: ${error.message}`, 'error'); - await disconnectPort(); - await tryAutoReconnect(); - } - }); - - newlineModeSelect.addEventListener('change', () => { - localStorage.setItem('newlineMode', newlineModeSelect.value); - }); - - // Forget device button clears stored device info - forgetDeviceBtn.addEventListener('click', async () => { - if (port) { - // Disconnect first - await port.disconnect(); - await port.forgetDevice(); - stopAutoReconnect(); - await disconnectPort(); - - setStatus('Device forgotten', 'info'); - } else { - setStatus('No device to forget', 'error'); - } - }); - - // Forget all devices button clears all stored device info - forgetAllDevicesBtn.addEventListener('click', async () => { - stopAutoReconnect(); - await disconnectPort(); - let ports = await serial.getPorts(); - if (ports.length > 0) { - for (const p of ports) { - await p.forgetDevice(); + try { + await this.currentPort.send(data); + this.commandHistoryIndex = -1; + this.appendCommandToHistory(sendText.replace(/[\r\n]+$/, '')); + commandLineInput.value = ''; + } catch (error) { + this.setStatus(`Send error: ${error.message}`, 'error'); + this.tryAutoReconnect(); } - setStatus('All devices forgotten', 'info'); - } else { - setStatus('No devices to forget', 'error'); } - }); - // Reset output button clears receiver - resetOutputBtn.addEventListener('click', () => { - receiverLines.innerHTML = ''; - }); - - // Reset button clears sender and receiver - resetAllBtn.addEventListener('click', () => { - senderLines.innerHTML = ''; - receiverLines.innerHTML = ''; - lastCommand = null; - lastCommandCount = 0; - lastCommandButton = null; - history.length = 0; - historyIndex = -1; - - // iterate and delete localStorage items - for (const key in localStorage) { - localStorage.removeItem(key); + toggleSendMode() { + if (this.sendMode === 'instant') { + this.setSendMode('command'); + } else { + this.setSendMode('instant'); + } } - }); + setSendMode(mode) { + this.sendMode = mode; + if (mode === 'instant') { + sendModeBtn.classList.remove('send-mode-command'); + sendModeBtn.classList.add('send-mode-instant'); + sendModeBtn.textContent = 'Instant mode'; + } else { + sendModeBtn.classList.remove('send-mode-instant'); + sendModeBtn.classList.add('send-mode-command'); + sendModeBtn.textContent = 'Command mode'; + } + localStorage.setItem('sendMode', this.sendMode); + } - // Disable input on load - commandLine.disabled = true; + normalizeNewlines(text) { + switch (newlineModeSelect.value) { + case 'CR': + return text.replace(/\r?\n/g, '\r'); + case 'CRLF': + return text.replace(/\r\n|[\r\n]/g, '\r\n'); + case 'ANY': + return text.replace(/\r\n|\r/g, '\n'); + default: + return text; + } + } - // Show warning if no WebUSB support - if (!serial.isWebUsbSupported()) { - setStatus('WebUSB not supported on this browser', 'error'); - } else { - // try to connect to any available device - connectPort(true); + copyOutput() { + const text = receivedDataScrollbox.innerText; + if (text) { + navigator.clipboard.writeText(text).then(() => { + this.setStatus('Output copied to clipboard', 'info'); + }, () => { + this.setStatus('Failed to copy output', 'error'); + }); + } else { + this.setStatus('No output to copy', 'error'); + } + } + + resetOutput() { + receivedDataScrollbox.innerHTML = ''; + } + + async resetAll() { + await this.forgetAllPorts(); + + // Clear localStorage + for (const key in localStorage) { + localStorage.removeItem(key); + } + + // reload the page + window.location.reload(); + } } -})(); + + const app = new Application(); +})() diff --git a/examples/device/webusb_serial/website/divider.js b/examples/device/webusb_serial/website/divider.js new file mode 100644 index 000000000..e52278005 --- /dev/null +++ b/examples/device/webusb_serial/website/divider.js @@ -0,0 +1,38 @@ +const resizer = document.getElementById('resizer'); +const leftColumn = resizer.previousElementSibling; +const rightColumn = resizer.nextElementSibling; +const container = resizer.parentNode; + +// Minimum and maximum width for left column in px +const minLeftWidth = 100; +const maxLeftWidth = container.clientWidth - 100; + +let isResizing = false; + +resizer.addEventListener('mousedown', e => { + e.preventDefault(); + isResizing = true; + document.body.style.userSelect = 'none'; // prevent text selection +}); + +document.addEventListener('mousemove', e => { + if (!isResizing) return; + + // Calculate new width of left column relative to container + const containerRect = container.getBoundingClientRect(); + let newLeftWidth = e.clientX - containerRect.left; + + // Clamp the width + newLeftWidth = Math.max(minLeftWidth, Math.min(newLeftWidth, containerRect.width - minLeftWidth)); + + // Set the left column's flex-basis (fixed width) + leftColumn.style.flex = '0 0 ' + newLeftWidth + 'px'; + rightColumn.style.flex = '1 1 0'; // fill remaining space +}); + +document.addEventListener('mouseup', e => { + if (isResizing) { + isResizing = false; + document.body.style.userSelect = ''; // restore user selection + } +}); diff --git a/examples/device/webusb_serial/website/index.html b/examples/device/webusb_serial/website/index.html index 8d18ff8cf..95bf20bf1 100644 --- a/examples/device/webusb_serial/website/index.html +++ b/examples/device/webusb_serial/website/index.html @@ -8,6 +8,7 @@ + @@ -20,44 +21,48 @@
- -
- + Click "Connect" to start
-

Sender

+

Command History

-
+
- - + +
+
-

Receiver

+

Received Data

-
+
diff --git a/examples/device/webusb_serial/website/serial.js b/examples/device/webusb_serial/website/serial.js index 2b60f2cc7..893dedbc7 100644 --- a/examples/device/webusb_serial/website/serial.js +++ b/examples/device/webusb_serial/website/serial.js @@ -1,16 +1,244 @@ 'use strict'; +/// Web Serial API Implementation +class SerialPort { + constructor(port) { + this.port = port; + this.reader = null; + this.writer = null; + this.readableStreamClosed = null; + this.isConnected = false; + this.readLoop = null; + this.initialized = false; + } + + /// Connect and start reading loop + async connect(options = { baudRate: 9600 }) { + if (this.initialized) { + return; + } + this.initialized = true; + await this.port.open(options); + + this.readableStreamClosed = this.port.readable; + this.reader = this.port.readable.getReader(); + + this.writer = this.port.writable.getWriter(); + this.isConnected = true; + this.readLoop = this._readLoop(); + } + + /// Internal continuous read loop + async _readLoop() { + while (this.isConnected) { + try { + const { value, done } = await this.reader.read(); + if (done || !this.isConnected) break; + if (value && this.onReceive) this.onReceive(value); + } catch (error) { + this.isConnected = false; + if (this.onReceiveError) this.onReceiveError(error); + } + } + } + + async _waitForReadLoopToFinish() { + if (this.readLoop) { + try { + await this.readLoop; + } catch (error) {} + this.readLoop = null; + } + } + + /// Stop reading and release port + async disconnect() { + this.isConnected = false; + await this._waitForReadLoopToFinish(); + + if (this.reader) { + try { + await this.reader.cancel(); + } catch (error) {} + this.reader.releaseLock(); + } + + if (this.writer) { + try { + await this.writer.close(); + } catch (error) {} + } + + if (this.readableStreamClosed) { + try { + await this.readableStreamClosed; + } catch (error) {} + } + + try { + await this.port.close(); + } catch (error) {} + } + + /// Send data to port + send(data) { + if (!this.writer) throw new Error('Port not connected'); + const encoder = new TextEncoder(); + return this.writer.write(encoder.encode(data)); + } + + async forgetDevice() {} +} + +/// WebUSB Implementation +class WebUsbSerialPort { + constructor(device) { + this.device = device; + this.interfaceNumber = 0; + this.endpointIn = 0; + this.endpointOut = 0; + this.isConnected = false; + this.readLoop = null; + this.initialized = false; + } + + isSameDevice(device) { + return this.device.vendorId === device.vendorId && this.device.productId === device.productId; + } + + /// Connect and start reading loop + async connect() { + if (this.initialized) { + const devices = await serial.getWebUsbSerialPorts(); + const device = devices.find(d => this.isSameDevice(d.device)); + if (device) { + this.device = device.device; + } else { + return false; + } + await this.device.open(); + } + this.initialized = true; + await this.device.open(); + try { + await this.device.reset(); + } catch (error) { } + + if (!this.device.configuration) { + await this.device.selectConfiguration(1); + } + + // Find interface with vendor-specific class (0xFF) and endpoints + for (const iface of this.device.configuration.interfaces) { + for (const alternate of iface.alternates) { + if (alternate.interfaceClass === 0xff) { + this.interfaceNumber = iface.interfaceNumber; + for (const endpoint of alternate.endpoints) { + if (endpoint.direction === 'out') this.endpointOut = endpoint.endpointNumber; + else if (endpoint.direction === 'in') this.endpointIn = endpoint.endpointNumber; + } + } + } + } + + if (this.interfaceNumber === undefined) { + throw new Error('No suitable interface found.'); + } + + await this.device.claimInterface(this.interfaceNumber); + await this.device.selectAlternateInterface(this.interfaceNumber, 0); + + // Set device to ENABLE (0x22 = SET_CONTROL_LINE_STATE, value 0x01 = activate) + await this.device.controlTransferOut({ + requestType: 'class', + recipient: 'interface', + request: 0x22, + value: 0x01, + index: this.interfaceNumber, + }); + + this.isConnected = true; + this.readLoop = this._readLoop(); + } + + async _waitForReadLoopToFinish() { + if (this.readLoop) { + try { + await this.readLoop; + } catch (error) {} + this.readLoop = null; + } + } + + /// Internal continuous read loop + async _readLoop() { + while (this.isConnected) { + try { + const result = await this.device.transferIn(this.endpointIn, 64); + if (result.data && this.onReceive) { + this.onReceive(result.data); + } + } catch (error) { + this.isConnected = false; + if (this.onReceiveError) { + this.onReceiveError(error); + } + } + } + } + + /// Stop reading and release device + async disconnect() { + this.isConnected = false; + await this._waitForReadLoopToFinish(); + try { + await this.device.controlTransferOut({ + requestType: 'class', + recipient: 'interface', + request: 0x22, + value: 0x00, + index: this.interfaceNumber, + }); + } catch (error) { + console.log(error); + } + await this.device.close(); + } + + /// Send data to device + send(data) { + return this.device.transferOut(this.endpointOut, data); + } + + async forgetDevice() { + await this.disconnect(); + await this.device.forget(); + } +} + +// Utility Functions const serial = { + isWebSerialSupported: () => 'serial' in navigator, isWebUsbSupported: () => 'usb' in navigator, - // Returns array of connected devices wrapped as serial.Port instances - async getPorts() { - const devices = await navigator.usb.getDevices(); - return devices.map(device => new serial.Port(device)); + async getSerialPorts() { + if (!this.isWebSerialSupported()) return []; + const ports = await navigator.serial.getPorts(); + return ports.map(port => new SerialPort(port)); }, - // Prompts user to select a device matching filters and wraps it in serial.Port - async requestPort() { + async getWebUsbSerialPorts() { + if (!this.isWebUsbSupported()) return []; + const devices = await navigator.usb.getDevices(); + return devices.map(device => new WebUsbSerialPort(device)); + }, + + async requestSerialPort() { + const port = await navigator.serial.requestPort(); + return new SerialPort(port); + }, + + async requestWebUsbSerialPort() { const filters = [ { vendorId: 0xcafe }, // TinyUSB { vendorId: 0x239a }, // Adafruit @@ -19,106 +247,6 @@ const serial = { { vendorId: 0x2341 }, // Arduino ]; const device = await navigator.usb.requestDevice({ filters }); - return new serial.Port(device); - }, - - Port: class { - constructor(device) { - this.device = device; - this.interfaceNumber = 0; - this.endpointIn = 0; - this.endpointOut = 0; - this.readLoopActive = false; - } - - portPointToSameDevice(port) { - if (this.device.vendorId !== port.device.vendorId) return false; - if (this.device.productId !== port.device.productId) return false; - if (this.device.serialNumber !== port.device.serialNumber) return false; - return true; - } - - // Connect and start reading loop - async connect() { - await this.device.open(); - - if (!this.device.configuration) { - await this.device.selectConfiguration(1); - } - - // Find interface with vendor-specific class (0xFF) and endpoints - for (const iface of this.device.configuration.interfaces) { - for (const alternate of iface.alternates) { - if (alternate.interfaceClass === 0xff) { - this.interfaceNumber = iface.interfaceNumber; - for (const endpoint of alternate.endpoints) { - if (endpoint.direction === 'out') this.endpointOut = endpoint.endpointNumber; - else if (endpoint.direction === 'in') this.endpointIn = endpoint.endpointNumber; - } - } - } - } - - if (this.interfaceNumber === undefined) { - throw new Error('No suitable interface found.'); - } - - await this.device.claimInterface(this.interfaceNumber); - await this.device.selectAlternateInterface(this.interfaceNumber, 0); - - // Set device to ENABLE (0x22 = SET_CONTROL_LINE_STATE, value 0x01 = activate) - await this.device.controlTransferOut({ - requestType: 'class', - recipient: 'interface', - request: 0x22, - value: 0x01, - index: this.interfaceNumber, - }); - - this.readLoopActive = true; - this._readLoop(); - } - - // Internal continuous read loop - async _readLoop() { - while (this.readLoopActive) { - try { - const result = await this.device.transferIn(this.endpointIn, 64); - if (result.data && this.onReceive) { - this.onReceive(result.data); - } - } catch (error) { - this.readLoopActive = false; - if (this.onReceiveError) { - this.onReceiveError(error); - } - } - } - } - - // Stop reading and release device - async disconnect() { - this.readLoopActive = false; - await this.device.controlTransferOut({ - requestType: 'class', - recipient: 'interface', - request: 0x22, - value: 0x00, - index: this.interfaceNumber, - }); - await this.device.close(); - } - - // Send data to device - send(data) { - return this.device.transferOut(this.endpointOut, data); - } - - async forgetDevice() { - if (this.device.opened) { - await this.device.close(); - } - await this.device.forget(); - } + return new WebUsbSerialPort(device); } }; diff --git a/examples/device/webusb_serial/website/style.css b/examples/device/webusb_serial/website/style.css index b73735d13..038a037c0 100644 --- a/examples/device/webusb_serial/website/style.css +++ b/examples/device/webusb_serial/website/style.css @@ -43,6 +43,10 @@ main { .controls-section, .status-section { padding: 1rem; flex-shrink: 0; + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 0.5rem; } /* Container for the two columns */ @@ -51,6 +55,7 @@ main { flex: 1; /* fill remaining vertical space */ width: 100%; + overflow: hidden; } /* Both columns flex equally and full height */ @@ -67,7 +72,7 @@ main { flex-direction: column; } -.sender-entry { +.command-history-entry { width: 100%; display: flex; flex-direction: row; @@ -85,7 +90,7 @@ main { color: inherit; } -.sender-entry:hover { +.command-history-entry:hover { background-color: #f0f0f0; } @@ -133,15 +138,6 @@ main { background-color: blue; } -/* UI Styles */ -.controls { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 1rem; - flex: 1 -} - .btn { padding: 0.5rem 1rem; font-size: 1rem; @@ -186,3 +182,10 @@ main { box-shadow: 0 0 6px rgba(0, 120, 215, 0.5); background-color: #fff; } + +.resizer { + width: 5px; + background-color: #ccc; + cursor: col-resize; + height: 100%; +} From eef5b92c9b168e11e29e8369b2f4d104fab42347 Mon Sep 17 00:00:00 2001 From: raldone01 Date: Sat, 5 Jul 2025 19:42:44 +0200 Subject: [PATCH 268/382] Choose a larger buffer. --- examples/device/webusb_serial/website/serial.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/device/webusb_serial/website/serial.js b/examples/device/webusb_serial/website/serial.js index 893dedbc7..2a07f6a0f 100644 --- a/examples/device/webusb_serial/website/serial.js +++ b/examples/device/webusb_serial/website/serial.js @@ -174,7 +174,7 @@ class WebUsbSerialPort { async _readLoop() { while (this.isConnected) { try { - const result = await this.device.transferIn(this.endpointIn, 64); + const result = await this.device.transferIn(this.endpointIn, 16384); if (result.data && this.onReceive) { this.onReceive(result.data); } From 28ded62c1c2034b29c7f3d4301386ce82e0c5ee5 Mon Sep 17 00:00:00 2001 From: raldone01 Date: Sat, 5 Jul 2025 19:42:44 +0200 Subject: [PATCH 269/382] Improve performance slightly --- .../webusb_serial/website/application.js | 415 ++++++++++++------ .../device/webusb_serial/website/divider.js | 75 ++-- .../device/webusb_serial/website/index.html | 16 +- .../device/webusb_serial/website/serial.js | 1 + .../device/webusb_serial/website/style.css | 33 +- 5 files changed, 363 insertions(+), 177 deletions(-) diff --git a/examples/device/webusb_serial/website/application.js b/examples/device/webusb_serial/website/application.js index 9e28c0204..0886f3441 100644 --- a/examples/device/webusb_serial/website/application.js +++ b/examples/device/webusb_serial/website/application.js @@ -2,27 +2,48 @@ (async () => { // bind to the html - const connectWebUsbSerialBtn = document.getElementById('connect_webusb_serial_btn'); - const connectSerialBtn = document.getElementById('connect_serial_btn'); - const disconnectBtn = document.getElementById('disconnect_btn'); + const uiConnectWebUsbSerialBtn = document.getElementById('connect_webusb_serial_btn'); + const uiConnectSerialBtn = document.getElementById('connect_serial_btn'); + const uiDisconnectBtn = document.getElementById('disconnect_btn'); - const newlineModeSelect = document.getElementById('newline_mode_select'); - const autoReconnectCheckbox = document.getElementById('auto_reconnect_checkbox'); - const forgetDeviceBtn = document.getElementById('forget_device_btn'); - const forgetAllDevicesBtn = document.getElementById('forget_all_devices_btn'); - const resetAllBtn = document.getElementById('reset_all_btn'); - const resetOutputBtn = document.getElementById('reset_output_btn'); - const copyOutputBtn = document.getElementById('copy_output_btn'); + const uiNewlineModeSelect = document.getElementById('newline_mode_select'); + const uiAutoReconnectCheckbox = document.getElementById('auto_reconnect_checkbox'); + const uiForgetDeviceBtn = document.getElementById('forget_device_btn'); + const uiForgetAllDevicesBtn = document.getElementById('forget_all_devices_btn'); + const uiResetAllBtn = document.getElementById('reset_all_btn'); + const uiCopyOutputBtn = document.getElementById('copy_output_btn'); + const uiDownloadOutputCsvBtn = document.getElementById('download_csv_output_btn'); - const statusSpan = document.getElementById('status_span'); + const uiStatusSpan = document.getElementById('status_span'); - const commandHistoryScrollbox = document.getElementById('command_history_scrollbox'); - const commandLineInput = document.getElementById('command_line_input'); - const sendModeBtn = document.getElementById('send_mode_btn'); + const uiCommandHistoryClearBtn = document.getElementById('clear_command_history_btn'); + const uiCommandHistoryScrollbox = document.getElementById('command_history_scrollbox'); + const uiCommandLineInput = document.getElementById('command_line_input'); + const uiSendModeBtn = document.getElementById('send_mode_btn'); - const receivedDataScrollbox = document.getElementById('received_data_scrollbox'); + const uiReceivedDataClearBtn = document.getElementById('clear_received_data_btn'); + const uiReceivedDataScrollbox = document.getElementById('received_data_scrollbox'); - const nearTheBottomThreshold = 100; // pixels from the bottom to trigger scroll + const uiNearTheBottomThreshold = 100; // pixels from the bottom to trigger scroll + + const maxCommandHistoryLength = 123; // max number of command history entries + const maxReceivedDataLength = 8192/8; // max number of received data entries + + class CommandHistoryEntry { + constructor(text) { + this.text = text; + this.time = Date.now(); + this.count = 1; + } + } + + class ReceivedDataEntry { + constructor(text) { + this.text = text; + this.time = Date.now(); + this.terminated = false; + } + } class Application { constructor() { @@ -33,122 +54,251 @@ this.reconnectTimeoutId = null; this.commandHistory = []; - this.commandHistoryIndex = -1; - this.lastCommandCount = 0; - this.lastCommand = null; - this.lastCommandBtn = null; + this.uiCommandHistoryIndex = -1; + + this.receivedData = []; // bind the UI elements - connectWebUsbSerialBtn.addEventListener('click', () => this.connectWebUsbSerialPort()); - connectSerialBtn.addEventListener('click', () => this.connectSerialPort()); - disconnectBtn.addEventListener('click', () => this.disconnectPort()); - newlineModeSelect.addEventListener('change', () => this.setNewlineMode()); - autoReconnectCheckbox.addEventListener('change', () => this.autoReconnectChanged()); - forgetDeviceBtn.addEventListener('click', () => this.forgetPort()); - forgetAllDevicesBtn.addEventListener('click', () => this.forgetAllPorts()); - resetAllBtn.addEventListener('click', () => this.resetAll()); - resetOutputBtn.addEventListener('click', () => this.resetOutput()); - copyOutputBtn.addEventListener('click', () => this.copyOutput()); - commandLineInput.addEventListener('keydown', (e) => this.handleCommandLineInput(e)); - sendModeBtn.addEventListener('click', () => this.toggleSendMode()); + uiConnectWebUsbSerialBtn.addEventListener('click', () => this.connectWebUsbSerialPort()); + uiConnectSerialBtn.addEventListener('click', () => this.connectSerialPort()); + uiDisconnectBtn.addEventListener('click', () => this.disconnectPort()); + uiNewlineModeSelect.addEventListener('change', () => this.setNewlineMode()); + uiAutoReconnectCheckbox.addEventListener('change', () => this.autoReconnectChanged()); + uiForgetDeviceBtn.addEventListener('click', () => this.forgetPort()); + uiForgetAllDevicesBtn.addEventListener('click', () => this.forgetAllPorts()); + uiResetAllBtn.addEventListener('click', () => this.resetAll()); + uiCopyOutputBtn.addEventListener('click', () => this.copyOutput()); + uiDownloadOutputCsvBtn.addEventListener('click', () => this.downloadOutputCsv()); + uiCommandHistoryClearBtn.addEventListener('click', () => this.clearCommandHistory()); + uiCommandLineInput.addEventListener('keydown', (e) => this.handleCommandLineInput(e)); + uiSendModeBtn.addEventListener('click', () => this.toggleSendMode()); + uiReceivedDataClearBtn.addEventListener('click', () => this.clearReceivedData()); // restore state from localStorage + try { + this.restoreState(); + } catch (error) { + console.error('Failed to restore state from localStorage', error); + this.resetAll(); + this.restoreState(); + } + this.updateUIConnectionState(); + this.connectWebUsbSerialPort(true); + } + + restoreState() { // Restore command history let savedCommandHistory = JSON.parse(localStorage.getItem('commandHistory') || '[]'); for (const cmd of savedCommandHistory) { this.appendCommandToHistory(cmd); } + // Restore received data + let savedReceivedData = JSON.parse(localStorage.getItem('receivedData') || '[]'); + for (let line of savedReceivedData) { + line.terminated = true; + this.appendReceivedData(line); + } + this.sendMode = localStorage.getItem('sendMode') || 'command'; this.setSendMode(this.sendMode); - autoReconnectCheckbox.checked = localStorage.getItem('autoReconnect') === 'true'; + uiAutoReconnectCheckbox.checked = !(localStorage.getItem('autoReconnect') === 'false'); let savedNewlineMode = localStorage.getItem('newlineMode'); if (savedNewlineMode) { - newlineModeSelect.value = savedNewlineMode; + uiNewlineModeSelect.value = savedNewlineMode; } - - this.connectWebUsbSerialPort(true); } - appendCommandToHistory(text) { - if (text === this.lastCommand) { - // Increment count and update button - this.lastCommandCount++; - this.lastCommandBtn.textContent = `${text} ×${this.lastCommandCount}`; - } else { - // Add a new entry to the command history - this.commandHistory.push(text); - localStorage.setItem('commandHistory', JSON.stringify(this.commandHistory)); - this.commandHistoryIndex = -1; + appendCommandToHistory(commandHistoryEntry) { + const wasNearBottom = uiCommandHistoryScrollbox.scrollHeight - uiCommandHistoryScrollbox.scrollTop <= uiCommandHistoryScrollbox.clientHeight + uiNearTheBottomThreshold; - const commandHistoryEntryBtn = document.createElement('button'); - commandHistoryEntryBtn.className = 'command-history-entry'; - commandHistoryEntryBtn.type = 'button'; - commandHistoryEntryBtn.textContent = text; - commandHistoryEntryBtn.addEventListener('click', () => { - if (commandLineInput.disabled) return; - commandLineInput.value = text; - commandLineInput.focus(); - }); - commandHistoryScrollbox.appendChild(commandHistoryEntryBtn); + let commandHistoryEntryBtn = null; - this.lastCommand = text; - this.lastCommandBtn = commandHistoryEntryBtn; + let lastCommandMatched = false; + if (this.commandHistory.length > 0) { + let lastCommandEntry = this.commandHistory[this.commandHistory.length - 1]; + if (lastCommandEntry.text === commandHistoryEntry.text) { + lastCommandEntry.count++; + lastCommandEntry.time = Date.now(); + lastCommandMatched = true; - // Scroll to the new entry if near the bottom - const distanceFromBottom = commandHistoryScrollbox.scrollHeight - (commandHistoryScrollbox.scrollTop + commandHistoryScrollbox.clientHeight); - if (distanceFromBottom < nearTheBottomThreshold) { - requestAnimationFrame(() => { - commandHistoryEntryBtn.scrollIntoView({ behavior: 'instant' }); - }); + // Update the last command entry + commandHistoryEntryBtn = uiCommandHistoryScrollbox.lastElementChild; + let time_str = new Date(lastCommandEntry.time).toLocaleString(); + commandHistoryEntryBtn.querySelector('.command-history-entry-time').textContent = time_str; + commandHistoryEntryBtn.querySelector('.command-history-entry-text').textContent = lastCommandEntry.text; + commandHistoryEntryBtn.querySelector('.command-history-entry-count').textContent = '×' + lastCommandEntry.count; } } - } + if (!lastCommandMatched) { + this.commandHistory.push(commandHistoryEntry); - appendLineToReceived(text) { - const div = document.createElement('div'); - div.textContent = text; - receivedDataScrollbox.appendChild(div); + // Create a new command history entry + commandHistoryEntryBtn = document.createElement('button'); + commandHistoryEntryBtn.className = 'command-history-entry'; + commandHistoryEntryBtn.type = 'button'; + let time_str = new Date(commandHistoryEntry.time).toLocaleString(); + commandHistoryEntryBtn.innerHTML = ` + ${time_str} + ${commandHistoryEntry.text} + ×${commandHistoryEntry.count} + `; + commandHistoryEntryBtn.addEventListener('click', () => { + if (uiCommandLineInput.disabled) return; + uiCommandLineInput.value = commandHistoryEntry.text; + uiCommandLineInput.focus(); + }); + + uiCommandHistoryScrollbox.appendChild(commandHistoryEntryBtn); + } + + // Limit the command history length + while (this.commandHistory.length > maxCommandHistoryLength) { + this.commandHistory.shift(); + uiCommandHistoryScrollbox.removeChild(uiCommandHistoryScrollbox.firstElementChild); + } + + // Save the command history to localStorage + localStorage.setItem('commandHistory', JSON.stringify(this.commandHistory)); // Scroll to the new entry if near the bottom - const distanceFromBottom = receivedDataScrollbox.scrollHeight - (receivedDataScrollbox.scrollTop + receivedDataScrollbox.clientHeight); - if (distanceFromBottom < nearTheBottomThreshold) { + if (wasNearBottom) { requestAnimationFrame(() => { - div.scrollIntoView({ behavior: 'instant' }); + uiCommandHistoryScrollbox.scrollTop = uiCommandHistoryScrollbox.scrollHeight; }); } } + clearCommandHistory() { + this.commandHistory = []; + uiCommandHistoryScrollbox.innerHTML = ''; + localStorage.removeItem('commandHistory'); + this.setStatus('Command history cleared', 'info'); + } + + appendReceivedData(receivedDataEntry) { + const wasNearBottom = uiReceivedDataScrollbox.scrollHeight - uiReceivedDataScrollbox.scrollTop <= uiReceivedDataScrollbox.clientHeight + uiNearTheBottomThreshold; + + let newReceivedDataEntries = []; + let updateLastReceivedDataEntry = false; + if (this.receivedData.length <= 0) { + newReceivedDataEntries.push(receivedDataEntry); + } else { + let lastReceivedDataEntry = this.receivedData[this.receivedData.length - 1]; + // Check if the last entry is terminated + if (lastReceivedDataEntry.terminated) { + newReceivedDataEntries.push(receivedDataEntry); + } else { + if (!lastReceivedDataEntry.terminated) { + updateLastReceivedDataEntry = true; + this.receivedData.pop(); + receivedDataEntry.text = lastReceivedDataEntry.text + receivedDataEntry.text; + } + // split the text into lines + let lines = receivedDataEntry.text.split(/\r?\n/); + // check if the last line is terminated by checking if it ends with an empty string + let lastLineTerminated = lines[lines.length - 1] === ''; + if (lastLineTerminated) { + lines.pop(); // remove the last empty line + } + + // create new entries for each line + for (let i = 0; i < lines.length; i++) { + let line = lines[i]; + let entry = new ReceivedDataEntry(line); + if (i === lines.length - 1) { + entry.terminated = lastLineTerminated; + } else { + entry.terminated = true; + } + newReceivedDataEntries.push(entry); + } + // if the last line is terminated, modify the last entry + if (lastLineTerminated) { + newReceivedDataEntries[newReceivedDataEntries.length - 1].terminated = true; + } else { + newReceivedDataEntries[newReceivedDataEntries.length - 1].terminated = false; + } + } + } + + this.receivedData.push(...newReceivedDataEntries); + + if (updateLastReceivedDataEntry) { + // update the rendering of the last entry + let lastReceivedDataEntryBtn = uiReceivedDataScrollbox.lastElementChild; + lastReceivedDataEntryBtn.querySelector('.received-data-entry-text').textContent = newReceivedDataEntries[0].text; + lastReceivedDataEntryBtn.querySelector('.received-data-entry-time').textContent = new Date(newReceivedDataEntries[0].time).toLocaleString(); + newReceivedDataEntries.shift(); + } + + // render the new entries + let documentFragment = document.createDocumentFragment(); + for (const entry of newReceivedDataEntries) { + let receivedDataEntryBtn = document.createElement('div'); + receivedDataEntryBtn.className = 'received-data-entry'; + receivedDataEntryBtn.innerHTML = ` + ${new Date(entry.time).toLocaleString()} + ${entry.text} + `; + documentFragment.appendChild(receivedDataEntryBtn); + } + uiReceivedDataScrollbox.appendChild(documentFragment); + + // Limit the received data length + while (this.receivedData.length > maxReceivedDataLength) { + this.receivedData.shift(); + uiReceivedDataScrollbox.removeChild(uiReceivedDataScrollbox.firstElementChild); + } + + // Save the received data to localStorage + localStorage.setItem('receivedData', JSON.stringify(this.receivedData)); + + // Scroll to the new entry if near the bottom + if (wasNearBottom) { + requestAnimationFrame(() => { + uiReceivedDataScrollbox.scrollTop = uiReceivedDataScrollbox.scrollHeight; + }); + } + } + + clearReceivedData() { + this.receivedData = []; + uiReceivedDataScrollbox.innerHTML = ''; + localStorage.removeItem('receivedData'); + this.setStatus('Received data cleared', 'info'); + } + setStatus(msg, level = 'info') { console.log(msg); - statusSpan.textContent = msg; - statusSpan.className = 'status status-' + level; + uiStatusSpan.textContent = msg; + uiStatusSpan.className = 'status status-' + level; } updateUIConnectionState() { if (this.currentPort && this.currentPort.isConnected) { - connectWebUsbSerialBtn.style.display = 'none'; - connectSerialBtn.style.display = 'none'; - disconnectBtn.style.display = 'block'; - commandLineInput.disabled = false; - commandLineInput.focus(); + uiConnectWebUsbSerialBtn.style.display = 'none'; + uiConnectSerialBtn.style.display = 'none'; + uiDisconnectBtn.style.display = 'block'; + uiCommandLineInput.disabled = false; + uiCommandLineInput.focus(); } else { if (serial.isWebUsbSupported()) { - connectWebUsbSerialBtn.style.display = 'block'; + uiConnectWebUsbSerialBtn.style.display = 'block'; } if (serial.isWebSerialSupported()) { - connectSerialBtn.style.display = 'block'; + uiConnectSerialBtn.style.display = 'block'; } if (!serial.isWebUsbSupported() && !serial.isWebSerialSupported()) { this.setStatus('Your browser does not support WebUSB or WebSerial', 'error'); } - disconnectBtn.style.display = 'none'; - commandLineInput.disabled = true; - commandLineInput.value = ''; - commandLineInput.blur(); + uiDisconnectBtn.style.display = 'none'; + uiCommandLineInput.disabled = true; + uiCommandLineInput.value = ''; + uiCommandLineInput.blur(); } } @@ -168,9 +318,10 @@ async onReceive(dataView) { this.updateUIConnectionState(); + let text = this.textDecoder.decode(dataView); - text = this.normalizeNewlines(text); - this.appendLineToReceived(text); + let receivedDataEntry = new ReceivedDataEntry(text); + this.appendReceivedData(receivedDataEntry); } async onReceiveError(error) { @@ -210,7 +361,7 @@ let first_time_connection = false; let grantedDevices = await serial.getWebUsbSerialPorts(); if (initial) { - if (!autoReconnectCheckbox.checked || grantedDevices.length === 0) { + if (!uiAutoReconnectCheckbox.checked || grantedDevices.length === 0) { return false; } @@ -303,18 +454,18 @@ } setNewlineMode() { - localStorage.setItem('newlineMode', newlineModeSelect.value); + localStorage.setItem('newlineMode', uiNewlineModeSelect.value); } autoReconnectChanged() { - if (autoReconnectCheckbox.checked) { + if (uiAutoReconnectCheckbox.checked) { this.setStatus('Auto-reconnect enabled', 'info'); this.tryAutoReconnect(); } else { this.setStatus('Auto-reconnect disabled', 'info'); this.stopAutoReconnect(); } - localStorage.setItem('autoReconnect', autoReconnectCheckbox.checked); + localStorage.setItem('autoReconnect', uiAutoReconnectCheckbox.checked); } stopAutoReconnect() { @@ -327,12 +478,12 @@ tryAutoReconnect() { this.updateUIConnectionState(); - if (!autoReconnectCheckbox.checked) return; + if (!uiAutoReconnectCheckbox.checked) return; if (this.reconnectTimeoutId !== null) return; // already trying this.setStatus('Attempting to auto-reconnect...', 'info'); this.reconnectTimeoutId = setTimeout(async () => { this.reconnectTimeoutId = null; - if (!autoReconnectCheckbox.checked) { + if (!uiAutoReconnectCheckbox.checked) { this.setStatus('Auto-reconnect stopped.', 'info'); return; } @@ -362,7 +513,7 @@ let sendText = ''; switch (e.key) { case 'Enter': - switch (newlineModeSelect.value) { + switch (uiNewlineModeSelect.value) { case 'CR': sendText = '\r'; break; case 'CRLF': sendText = '\r\n'; break; default: sendText = '\n'; break; @@ -387,7 +538,7 @@ sendText = e.key; } try { - await port.send(this.textEncoder.encode(sendText)); + await this.currentPort.send(this.textEncoder.encode(sendText)); } catch (error) { this.setStatus(`Send error: ${error.message}`, 'error'); this.tryAutoReconnect(); @@ -402,24 +553,24 @@ e.preventDefault(); if (this.commandHistory.length === 0) return; if (e.key === 'ArrowUp') { - if (this.commandHistoryIndex === -1) this.commandHistoryIndex = this.commandHistory.length - 1; - else if (this.commandHistoryIndex > 0) this.commandHistoryIndex--; + if (this.uiCommandHistoryIndex === -1) this.uiCommandHistoryIndex = this.commandHistory.length - 1; + else if (this.uiCommandHistoryIndex > 0) this.uiCommandHistoryIndex--; } else if (e.key === 'ArrowDown') { - if (this.commandHistoryIndex !== -1) this.commandHistoryIndex++; - if (this.commandHistoryIndex >= this.commandHistory.length) this.commandHistoryIndex = -1; + if (this.uiCommandHistoryIndex !== -1) this.uiCommandHistoryIndex++; + if (this.uiCommandHistoryIndex >= this.commandHistory.length) this.uiCommandHistoryIndex = -1; } - commandLineInput.value = this.commandHistoryIndex === -1 ? '' : this.commandHistory[this.commandHistoryIndex]; + uiCommandLineInput.value = this.uiCommandHistoryIndex === -1 ? '' : this.commandHistory[this.uiCommandHistoryIndex].text; return; } if (e.key !== 'Enter' || !this.currentPort.isConnected) return; e.preventDefault(); - const text = commandLineInput.value; + const text = uiCommandLineInput.value; if (!text) return; // Convert to Uint8Array with newline based on config let sendText = text; - switch (newlineModeSelect.value) { + switch (uiNewlineModeSelect.value) { case 'CR': sendText += '\r'; break; @@ -434,9 +585,11 @@ try { await this.currentPort.send(data); - this.commandHistoryIndex = -1; - this.appendCommandToHistory(sendText.replace(/[\r\n]+$/, '')); - commandLineInput.value = ''; + this.uiCommandHistoryIndex = -1; + let history_cmd_text = sendText.replace(/[\r\n]+$/, ''); + let history_entry = new CommandHistoryEntry(history_cmd_text); + this.appendCommandToHistory(history_entry); + uiCommandLineInput.value = ''; } catch (error) { this.setStatus(`Send error: ${error.message}`, 'error'); this.tryAutoReconnect(); @@ -454,32 +607,26 @@ setSendMode(mode) { this.sendMode = mode; if (mode === 'instant') { - sendModeBtn.classList.remove('send-mode-command'); - sendModeBtn.classList.add('send-mode-instant'); - sendModeBtn.textContent = 'Instant mode'; + uiSendModeBtn.classList.remove('send-mode-command'); + uiSendModeBtn.classList.add('send-mode-instant'); + uiSendModeBtn.textContent = 'Instant mode'; } else { - sendModeBtn.classList.remove('send-mode-instant'); - sendModeBtn.classList.add('send-mode-command'); - sendModeBtn.textContent = 'Command mode'; + uiSendModeBtn.classList.remove('send-mode-instant'); + uiSendModeBtn.classList.add('send-mode-command'); + uiSendModeBtn.textContent = 'Command mode'; } localStorage.setItem('sendMode', this.sendMode); } - normalizeNewlines(text) { - switch (newlineModeSelect.value) { - case 'CR': - return text.replace(/\r?\n/g, '\r'); - case 'CRLF': - return text.replace(/\r\n|[\r\n]/g, '\r\n'); - case 'ANY': - return text.replace(/\r\n|\r/g, '\n'); - default: - return text; - } - } - copyOutput() { - const text = receivedDataScrollbox.innerText; + let text = ''; + for (const entry of this.receivedData) { + text += entry.text; + if (entry.terminated) { + text += '\n'; + } + } + if (text) { navigator.clipboard.writeText(text).then(() => { this.setStatus('Output copied to clipboard', 'info'); @@ -491,8 +638,22 @@ } } - resetOutput() { - receivedDataScrollbox.innerHTML = ''; + downloadOutputCsv() { + // save , + let csvContent = 'data:text/csv;charset=utf-8,'; + for (const entry of this.receivedData) { + let line = new Date(entry.time).toISOString() + ',"' + entry.text.replace(/[\r\n]+$/, '') + '"'; + csvContent += line + '\n'; + } + + const encodedUri = encodeURI(csvContent); + const link = document.createElement('a'); + link.setAttribute('href', encodedUri); + const filename = new Date().toISOString() + '_tinyusb_received_serial_data.csv'; + link.setAttribute('download', filename); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); } async resetAll() { diff --git a/examples/device/webusb_serial/website/divider.js b/examples/device/webusb_serial/website/divider.js index e52278005..b67d0e429 100644 --- a/examples/device/webusb_serial/website/divider.js +++ b/examples/device/webusb_serial/website/divider.js @@ -1,38 +1,47 @@ -const resizer = document.getElementById('resizer'); -const leftColumn = resizer.previousElementSibling; -const rightColumn = resizer.nextElementSibling; -const container = resizer.parentNode; +(async () => { -// Minimum and maximum width for left column in px -const minLeftWidth = 100; -const maxLeftWidth = container.clientWidth - 100; + const uiResizer = document.getElementById('resizer'); + const uiLeftColumn = uiResizer.previousElementSibling; + const uiRightColumn = uiResizer.nextElementSibling; + const uiParent = uiResizer.parentElement; -let isResizing = false; + let isResizing = false; + let abortSignal = null; -resizer.addEventListener('mousedown', e => { - e.preventDefault(); - isResizing = true; - document.body.style.userSelect = 'none'; // prevent text selection -}); + function onMouseMove(e) { + // we resize the columns by applying felx: to the columns -document.addEventListener('mousemove', e => { - if (!isResizing) return; - - // Calculate new width of left column relative to container - const containerRect = container.getBoundingClientRect(); - let newLeftWidth = e.clientX - containerRect.left; - - // Clamp the width - newLeftWidth = Math.max(minLeftWidth, Math.min(newLeftWidth, containerRect.width - minLeftWidth)); - - // Set the left column's flex-basis (fixed width) - leftColumn.style.flex = '0 0 ' + newLeftWidth + 'px'; - rightColumn.style.flex = '1 1 0'; // fill remaining space -}); - -document.addEventListener('mouseup', e => { - if (isResizing) { - isResizing = false; - document.body.style.userSelect = ''; // restore user selection + // compute the percentage the mouse is in the parent + const percentage = (e.clientX - uiParent.offsetLeft) / uiParent.clientWidth; + // clamp the percentage between 0.1 and 0.9 + const clampedPercentage = Math.max(0.1, Math.min(0.9, percentage)); + // set the flex property of the columns + uiLeftColumn.style.flex = `${clampedPercentage}`; + uiRightColumn.style.flex = `${1 - clampedPercentage}`; } -}); + + function onMouseUp(e) { + // restore user selection + document.body.style.userSelect = ''; + + // remove the mousemove and mouseup events + if (abortSignal) { + abortSignal.abort(); + abortSignal = null; + } + } + + uiResizer.addEventListener('mousedown', e => { + e.preventDefault(); + isResizing = true; + + // prevent text selection + document.body.style.userSelect = 'none'; + + // register the mousemove and mouseup events + abortSignal = new AbortController(); + document.addEventListener('mousemove', onMouseMove, { signal: abortSignal.signal }); + document.addEventListener('mouseup', onMouseUp, { signal: abortSignal.signal }); + }); + +})(); diff --git a/examples/device/webusb_serial/website/index.html b/examples/device/webusb_serial/website/index.html index 95bf20bf1..87fcfd6aa 100644 --- a/examples/device/webusb_serial/website/index.html +++ b/examples/device/webusb_serial/website/index.html @@ -25,7 +25,7 @@ diff --git a/examples/device/webusb_serial/website/serial.js b/examples/device/webusb_serial/website/serial.js index 55035c81f..19827f016 100644 --- a/examples/device/webusb_serial/website/serial.js +++ b/examples/device/webusb_serial/website/serial.js @@ -116,7 +116,7 @@ class SerialPort { if (!this._port.writable) { throw new Error('Port is not writable'); } - this._writer = port.writeable.getWriter(); + this._writer = this._port.writable.getWriter(); if (!this._writer) { throw new Error('Failed to get writer from port'); } @@ -141,6 +141,13 @@ class WebUsbSerialPort { this._readLoopPromise = null; this._initialized = false; this._keepReading = true; + + this._vendorId = device.vendorId; + this._productId = device.productId; + } + + _isSameWebUsbSerialPort(webUsbSerialPort) { + return this._vendorId === webUsbSerialPort._vendorId && this._productId === webUsbSerialPort._productId; } /// Connect and start reading loop @@ -152,14 +159,9 @@ class WebUsbSerialPort { console.error('Error disconnecting previous device:', error); } - if (this._readLoopPromise) { - try { - await this._readLoopPromise; - } catch (error) { - console.error('Error in read loop:', error); - } - } - this._readLoopPromise = null; + const webUsbSerialPorts = await serial.getWebUsbSerialPorts(); + const webUsbSerialPort = webUsbSerialPorts.find(serialPort => this._isSameWebUsbSerialPort(serialPort)); + this._device = webUsbSerialPort ? webUsbSerialPort._device : this._device; } this._initialized = true; diff --git a/examples/device/webusb_serial/website/style.css b/examples/device/webusb_serial/website/style.css index 3af2668e0..7b8b6029d 100644 --- a/examples/device/webusb_serial/website/style.css +++ b/examples/device/webusb_serial/website/style.css @@ -221,6 +221,12 @@ body.dark-mode { color: #d4d4d4; } +body.dark-mode input[type="checkbox"] { + border-color: #888; + accent-color: #2e2e2e; + opacity: 0.8; +} + body.dark-mode .btn-theme { background-color: #b0b0b0; color: #000; @@ -251,6 +257,7 @@ body.dark-mode .input:focus { body.dark-mode .scrollbox { background-color: #252526; + scrollbar-color: #555 #2e2e2e; border: 1px solid #444; } @@ -287,7 +294,3 @@ body.dark-mode option { background-color: #3c3c3c; color: #f0f0f0; } - -body.dark-mode .scrollbox { - scrollbar-color: #555 #2e2e2e; -} From b67e00892c726f27051b407486d9f0c04ff687f9 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 31 Jul 2025 21:52:59 +0700 Subject: [PATCH 317/382] add ci build for all at32, use linker and startup from mcu cmsis instead of local files --- .github/workflows/ci_set_matrix.py | 2 +- .../cmake/cpu/cortex-m4-nofpu.cmake | 30 + .../build_system/make/cpu/cortex-m4-nofpu.mk | 20 + examples/device/net_lwip_webserver/skip.txt | 1 + .../AT_START_F402_405/AT32F405xC_FLASH.ld | 154 ----- .../boards/AT_START_F402_405/board.cmake | 2 + .../boards/AT_START_F402_405/board.mk | 8 +- hw/bsp/at32f402_405/family.cmake | 48 +- hw/bsp/at32f402_405/family.mk | 35 +- hw/bsp/at32f402_405/startup_at32f402_405.s | 486 --------------- .../AT_START_F403A_407/AT32F403AxG_FLASH.ld | 154 ----- .../boards/AT_START_F403A_407/board.cmake | 2 + .../boards/AT_START_F403A_407/board.mk | 8 +- hw/bsp/at32f403a_407/family.cmake | 48 +- hw/bsp/at32f403a_407/family.mk | 32 +- hw/bsp/at32f403a_407/startup_at32f403a_407.s | 478 --------------- .../boards/AT_START_F413/AT32F413xC_FLASH.ld | 168 ------ .../at32f413/boards/AT_START_F413/board.cmake | 8 + hw/bsp/at32f413/boards/AT_START_F413/board.mk | 8 +- hw/bsp/at32f413/family.c | 105 ++-- hw/bsp/at32f413/family.cmake | 108 ++++ hw/bsp/at32f413/family.mk | 32 +- hw/bsp/at32f413/startup_at32f413.s | 431 ------------- .../boards/AT_START_F415/AT32F415xC_FLASH.ld | 154 ----- .../at32f415/boards/AT_START_F415/board.cmake | 11 + hw/bsp/at32f415/boards/AT_START_F415/board.mk | 8 +- hw/bsp/at32f415/family.c | 196 +++--- hw/bsp/at32f415/family.cmake | 108 ++++ hw/bsp/at32f415/family.mk | 33 +- hw/bsp/at32f415/startup_at32f415.s | 407 ------------- .../boards/AT_START_F423/AT32F423xC_FLASH.ld | 154 ----- .../at32f423/boards/AT_START_F423/board.cmake | 2 + hw/bsp/at32f423/boards/AT_START_F423/board.mk | 8 +- hw/bsp/at32f423/family.cmake | 48 +- hw/bsp/at32f423/family.mk | 34 +- hw/bsp/at32f423/startup_at32f423.s | 483 --------------- .../boards/AT_START_F425/AT32F425x8_FLASH.ld | 153 ----- .../at32f425/boards/AT_START_F425/board.cmake | 12 + hw/bsp/at32f425/boards/AT_START_F425/board.mk | 9 +- hw/bsp/at32f425/family.c | 157 +++-- hw/bsp/at32f425/family.cmake | 108 ++++ hw/bsp/at32f425/family.mk | 33 +- hw/bsp/at32f425/startup_at32f425.s | 309 ---------- .../AT_START_F435_437/AT32F437xM_FLASH.ld | 154 ----- .../boards/AT_START_F435_437/board.cmake | 8 + .../boards/AT_START_F435_437/board.mk | 7 +- hw/bsp/at32f435_437/family.c | 177 +++--- hw/bsp/at32f435_437/family.cmake | 114 ++++ hw/bsp/at32f435_437/family.mk | 36 +- hw/bsp/at32f435_437/startup_at32f435_437.s | 569 ------------------ 50 files changed, 1023 insertions(+), 4837 deletions(-) create mode 100644 examples/build_system/cmake/cpu/cortex-m4-nofpu.cmake create mode 100644 examples/build_system/make/cpu/cortex-m4-nofpu.mk delete mode 100644 hw/bsp/at32f402_405/boards/AT_START_F402_405/AT32F405xC_FLASH.ld delete mode 100644 hw/bsp/at32f402_405/startup_at32f402_405.s delete mode 100644 hw/bsp/at32f403a_407/boards/AT_START_F403A_407/AT32F403AxG_FLASH.ld delete mode 100644 hw/bsp/at32f403a_407/startup_at32f403a_407.s delete mode 100644 hw/bsp/at32f413/boards/AT_START_F413/AT32F413xC_FLASH.ld create mode 100644 hw/bsp/at32f413/boards/AT_START_F413/board.cmake create mode 100644 hw/bsp/at32f413/family.cmake delete mode 100644 hw/bsp/at32f413/startup_at32f413.s delete mode 100644 hw/bsp/at32f415/boards/AT_START_F415/AT32F415xC_FLASH.ld create mode 100644 hw/bsp/at32f415/boards/AT_START_F415/board.cmake create mode 100644 hw/bsp/at32f415/family.cmake delete mode 100644 hw/bsp/at32f415/startup_at32f415.s delete mode 100644 hw/bsp/at32f423/boards/AT_START_F423/AT32F423xC_FLASH.ld delete mode 100644 hw/bsp/at32f423/startup_at32f423.s delete mode 100644 hw/bsp/at32f425/boards/AT_START_F425/AT32F425x8_FLASH.ld create mode 100644 hw/bsp/at32f425/boards/AT_START_F425/board.cmake create mode 100644 hw/bsp/at32f425/family.cmake delete mode 100644 hw/bsp/at32f425/startup_at32f425.s delete mode 100644 hw/bsp/at32f435_437/boards/AT_START_F435_437/AT32F437xM_FLASH.ld create mode 100644 hw/bsp/at32f435_437/boards/AT_START_F435_437/board.cmake create mode 100644 hw/bsp/at32f435_437/family.cmake delete mode 100644 hw/bsp/at32f435_437/startup_at32f435_437.s diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index 5fe805c82..4870ec28e 100755 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -15,7 +15,7 @@ toolchain_list = [ # family: [supported toolchain] family_list = { - "at32f403a_407 at32f423": ["arm-gcc"], + "at32f402_405 at32f403a_407 at32f413 at32f415 at32f423 at32f425 at32f435_437": ["arm-gcc"], "broadcom_32bit": ["arm-gcc"], "broadcom_64bit": ["aarch64-gcc"], "ch32v10x ch32v20x ch32v307 fomu gd32vf103": ["riscv-gcc"], diff --git a/examples/build_system/cmake/cpu/cortex-m4-nofpu.cmake b/examples/build_system/cmake/cpu/cortex-m4-nofpu.cmake new file mode 100644 index 000000000..eec924986 --- /dev/null +++ b/examples/build_system/cmake/cpu/cortex-m4-nofpu.cmake @@ -0,0 +1,30 @@ +if (TOOLCHAIN STREQUAL "gcc") + set(TOOLCHAIN_COMMON_FLAGS + -mthumb + -mcpu=cortex-m4 + -mfloat-abi=soft + ) + if (NOT DEFINED FREERTOS_PORT) + set(FREERTOS_PORT GCC_ARM_CM3 CACHE INTERNAL "") + endif () + +elseif (TOOLCHAIN STREQUAL "clang") + set(TOOLCHAIN_COMMON_FLAGS + --target=arm-none-eabi + -mcpu=cortex-m4 + ) + if (NOT DEFINED FREERTOS_PORT) + set(FREERTOS_PORT GCC_ARM_CM3 CACHE INTERNAL "") + endif () + +elseif (TOOLCHAIN STREQUAL "iar") + set(TOOLCHAIN_COMMON_FLAGS + --cpu cortex-m4 + --fpu none + ) + + if (NOT DEFINED FREERTOS_PORT) + set(FREERTOS_PORT IAR_ARM_CM3 CACHE INTERNAL "") + endif () + +endif () diff --git a/examples/build_system/make/cpu/cortex-m4-nofpu.mk b/examples/build_system/make/cpu/cortex-m4-nofpu.mk new file mode 100644 index 000000000..ac2916005 --- /dev/null +++ b/examples/build_system/make/cpu/cortex-m4-nofpu.mk @@ -0,0 +1,20 @@ +ifeq ($(TOOLCHAIN),gcc) + CFLAGS += \ + -mthumb \ + -mcpu=cortex-m4 \ + -mfloat-abi=soft + +else ifeq ($(TOOLCHAIN),clang) + CFLAGS += \ + --target=arm-none-eabi \ + -mcpu=cortex-m4 + +else ifeq ($(TOOLCHAIN),iar) + CFLAGS += --cpu cortex-m4 --fpu none + ASFLAGS += --cpu cortex-m4 --fpu none + +else + $(error "TOOLCHAIN is not supported") +endif + +FREERTOS_PORTABLE_SRC ?= $(FREERTOS_PORTABLE_PATH)/ARM_CM3 diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index 20a264387..6f66efb53 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -15,6 +15,7 @@ mcu:STM32N6 family:broadcom_64bit family:broadcom_32bit family:espressif +board:AT_START_F425 board:curiosity_nano board:frdm_kl25z # lpc55 has weird error 'ncm_interface' causes a section type conflict with 'ntb_parameters' diff --git a/hw/bsp/at32f402_405/boards/AT_START_F402_405/AT32F405xC_FLASH.ld b/hw/bsp/at32f402_405/boards/AT_START_F402_405/AT32F405xC_FLASH.ld deleted file mode 100644 index 0b3550ddb..000000000 --- a/hw/bsp/at32f402_405/boards/AT_START_F402_405/AT32F405xC_FLASH.ld +++ /dev/null @@ -1,154 +0,0 @@ -/* -***************************************************************************** -** -** File : AT32F405xC_FLASH.ld -** -** Abstract : Linker script for AT32F405xC Device with -** 256KByte FLASH, 102KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : Artery Tek AT32 -** -** Environment : Arm gcc toolchain -** -***************************************************************************** -*/ - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Highest address of the user mode stack */ -_estack = 0x20019800; /* end of RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0x2000; /* required amount of heap */ -_Min_Stack_Size = 0x4000; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ -FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 102K -} - -/* Define output sections */ -SECTIONS -{ - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - /* Constant data goes into FLASH */ - .rodata : - { - . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - . = ALIGN(4); - } >FLASH - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array*)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM AT> FLASH - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss section */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } -} diff --git a/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.cmake b/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.cmake index f27d73d7b..0d09680a1 100644 --- a/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.cmake +++ b/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.cmake @@ -1,4 +1,6 @@ set(MCU_VARIANT AT32F405RCT7) +set(MCU_LINKER_NAME AT32F405xC) + set(JLINK_DEVICE ${MCU_VARIANT}) function(update_board TARGET) diff --git a/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.mk b/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.mk index e09211794..25a719ccf 100644 --- a/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.mk +++ b/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.mk @@ -1,5 +1,7 @@ -JLINK_DEVICE = AT32F405RCT7 -LD_FILE = $(BOARD_PATH)/AT32F405xC_FLASH.ld +MCU_VARIANT = AT32F405RCT7 +MCU_LINKER_NAME = AT32F405xC + +JLINK_DEVICE = ${MCU_VARIANT} CFLAGS += \ - -DAT32F405RCT7 + -D${MCU_VARIANT} diff --git a/hw/bsp/at32f402_405/family.cmake b/hw/bsp/at32f402_405/family.cmake index 2d2cdc026..010e36b88 100644 --- a/hw/bsp/at32f402_405/family.cmake +++ b/hw/bsp/at32f402_405/family.cmake @@ -1,9 +1,9 @@ include_guard() -set(AT_FAMILY at32f402_405) -set(AT_SDK_LIB ${TOP}/hw/mcu/artery/${AT_FAMILY}/libraries) +set(AT32_FAMILY at32f402_405) +set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries) -string(TOUPPER ${AT_FAMILY} AT_FAMILY_UPPER) +string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER) # include board specific include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) @@ -12,15 +12,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) -set(FAMILY_MCUS ${AT_FAMILY_UPPER} CACHE INTERNAL "") - -# extract variant linker name -string(LENGTH ${MCU_VARIANT} MCU_VARIANT_LEN) -math(EXPR MCU_FLASH_CODE_INDEX "${MCU_VARIANT_LEN} - 3") -math(EXPR MCU_VARIANT_PREFIX_LEN "${MCU_FLASH_CODE_INDEX} - 1") -string(SUBSTRING ${MCU_VARIANT} ${MCU_FLASH_CODE_INDEX} 1 MCU_FLASH_CODE) -string(SUBSTRING ${MCU_VARIANT} 0 ${MCU_VARIANT_PREFIX_LEN} MCU_VARIANT_PREFIX) -set(MCU_LINKER_NAME ${MCU_VARIANT_PREFIX}x${MCU_FLASH_CODE}) +set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") #------------------------------------ # BOARD_TARGET @@ -32,30 +24,30 @@ function(add_board_target BOARD_TARGET) endif () # Startup & Linker script - set(STARTUP_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/startup_${AT_FAMILY}.s) + set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${AT_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT_FAMILY}.s) + set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${AT_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) + set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) endif () set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${AT_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) + set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) add_library(${BOARD_TARGET} STATIC - ${AT_SDK_LIB}/cmsis/cm4/device_support/system_${AT_FAMILY}.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_gpio.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_misc.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_usart.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_acc.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_crm.c + ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${AT_SDK_LIB}/cmsis/cm4/core_support - ${AT_SDK_LIB}/cmsis/cm4/device_support - ${AT_SDK_LIB}/drivers/inc + ${AT32_SDK_LIB}/cmsis/cm4/core_support + ${AT32_SDK_LIB}/cmsis/cm4/device_support + ${AT32_SDK_LIB}/drivers/inc ) target_compile_definitions(${BOARD_TARGET} PUBLIC BOARD_TUD_RHPORT=0 @@ -97,8 +89,8 @@ function(family_configure_example TARGET RTOS) # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT_FAMILY}_clock.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT_FAMILY}_int.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c ) target_include_directories(${TARGET} PUBLIC # family, hw, board @@ -108,7 +100,7 @@ function(family_configure_example TARGET RTOS) ) # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${AT_FAMILY_UPPER}) + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) target_sources(${TARGET} PUBLIC ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c diff --git a/hw/bsp/at32f402_405/family.mk b/hw/bsp/at32f402_405/family.mk index 91b5baffb..60a0f93e9 100644 --- a/hw/bsp/at32f402_405/family.mk +++ b/hw/bsp/at32f402_405/family.mk @@ -1,8 +1,5 @@ -# Submodules -AT32F402_405_SDK = hw/mcu/artery/at32f402_405 - -# AT32 SDK path -AT32F402_405_SDK_SRC = $(AT32F402_405_SDK)/libraries +AT32_FAMILY = at32f402_405 +AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries include $(TOP)/$(BOARD_PATH)/board.mk @@ -13,6 +10,7 @@ CFLAGS_GCC += \ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_AT32F402_405 \ + -DBOARD_TUD_RHPORT=0 \ -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED LDFLAGS_GCC += \ @@ -22,23 +20,26 @@ SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ src/portable/synopsys/dwc2/hcd_dwc2.c \ src/portable/synopsys/dwc2/dwc2_common.c \ - $(AT32F402_405_SDK_SRC)/drivers/src/at32f402_405_gpio.c \ - $(AT32F402_405_SDK_SRC)/drivers/src/at32f402_405_misc.c \ - $(AT32F402_405_SDK_SRC)/drivers/src/at32f402_405_usart.c \ - $(AT32F402_405_SDK_SRC)/drivers/src/at32f402_405_crm.c \ - $(AT32F402_405_SDK_SRC)/drivers/src/at32f402_405_acc.c \ - $(AT32F402_405_SDK_SRC)/cmsis/cm4/device_support/system_at32f402_405.c + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_acc.c \ + $(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(AT32F402_405_SDK_SRC)/drivers/inc \ - $(TOP)/$(AT32F402_405_SDK_SRC)/cmsis/cm4/core_support \ - $(TOP)/$(AT32F402_405_SDK_SRC)/cmsis/cm4/device_support + $(TOP)/$(AT32_SDK_LIB)/drivers/inc \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support -SRC_S += \ - $(FAMILY_PATH)/startup_at32f402_405.s +SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s +SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s + +LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld +LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf # For freeRTOS port source -#FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4 +FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F flash: flash-atlink diff --git a/hw/bsp/at32f402_405/startup_at32f402_405.s b/hw/bsp/at32f402_405/startup_at32f402_405.s deleted file mode 100644 index 9b0dad9ef..000000000 --- a/hw/bsp/at32f402_405/startup_at32f402_405.s +++ /dev/null @@ -1,486 +0,0 @@ -/** - ****************************************************************************** - * @file startup_at32f402_405.s - * @brief at32f402_405 devices vector table for gcc toolchain. - * this module performs: - * - set the initial sp - * - set the initial pc == reset_handler, - * - set the vector table entries with the exceptions isr address - * - configure the clock system and the external sram to - * be used as data memory (optional, to be enabled by user) - * - branches to main in the c library (which eventually - * calls main()). - * after reset the cortex-m4 processor is in thread mode, - * priority is privileged, and the stack is set to main. - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M3. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDT_IRQHandler /* Window Watchdog Timer */ - .word PVM_IRQHandler /* PVM through EXINT Line detect */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXINT line */ - .word ERTC_WKUP_IRQHandler /* ERTC Wakeup through the EXINT line */ - .word FLASH_IRQHandler /* Flash */ - .word CRM_IRQHandler /* CRM */ - .word EXINT0_IRQHandler /* EXINT Line 0 */ - .word EXINT1_IRQHandler /* EXINT Line 1 */ - .word EXINT2_IRQHandler /* EXINT Line 2 */ - .word EXINT3_IRQHandler /* EXINT Line 3 */ - .word EXINT4_IRQHandler /* EXINT Line 4 */ - .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ - .word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */ - .word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */ - .word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */ - .word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */ - .word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */ - .word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */ - .word ADC1_IRQHandler /* ADC1 */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SE_IRQHandler /* CAN1 SE */ - .word EXINT9_5_IRQHandler /* EXINT Line [9:5] */ - .word TMR1_BRK_TMR9_IRQHandler /* TMR1 Brake and TMR9 */ - .word TMR1_OVF_TMR10_IRQHandler /* TMR1 Overflow and TMR10 */ - .word TMR1_TRG_HALL_TMR11_IRQHandler /* TMR1 Trigger and hall and TMR11 */ - .word TMR1_CH_IRQHandler /* TMR1 Channel */ - .word TMR2_GLOBAL_IRQHandler /* TMR2 */ - .word TMR3_GLOBAL_IRQHandler /* TMR3 */ - .word TMR4_GLOBAL_IRQHandler /* TMR4 */ - .word I2C1_EVT_IRQHandler /* I2C1 Event */ - .word I2C1_ERR_IRQHandler /* I2C1 Error */ - .word I2C2_EVT_IRQHandler /* I2C2 Event */ - .word I2C2_ERR_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXINT15_10_IRQHandler /* EXINT Line [15:10] */ - .word ERTCAlarm_IRQHandler /* ERTC Alarm through EXINT Line */ - .word OTGFS1_WKUP_IRQHandler /* OTGFS1 Wakeup from suspend */ - .word 0 /* Reserved */ - .word TMR13_GLOBAL_IRQHandler /* TMR13 */ - .word TMR14_GLOBAL_IRQHandler /* TMR14 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word SPI3_IRQHandler /* SPI3 */ - .word USART4_IRQHandler /* USART4 */ - .word USART5_IRQHandler /* USART5 */ - .word TMR6_GLOBAL_IRQHandler /* TMR6 */ - .word TMR7_GLOBAL_IRQHandler /* TMR7 */ - .word DMA2_Channel1_IRQHandler /* DMA1 Channel 1 */ - .word DMA2_Channel2_IRQHandler /* DMA1 Channel 2 */ - .word DMA2_Channel3_IRQHandler /* DMA1 Channel 3 */ - .word DMA2_Channel4_IRQHandler /* DMA1 Channel 4 */ - .word DMA2_Channel5_IRQHandler /* DMA1 Channel 5 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word OTGFS1_IRQHandler /* OTGFS1 */ - .word DMA2_Channel6_IRQHandler /* DMA2 Channel 6 */ - .word DMA2_Channel7_IRQHandler /* DMA2 Channel 7 */ - .word 0 /* Reserved */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EVT_IRQHandler /* I2C3 Event */ - .word I2C3_ERR_IRQHandler /* I2C3 Error */ - .word OTGHS_EP1_OUT_IRQHandler /* OTGHS endpoint1 out */ - .word OTGHS_EP1_IN_IRQHandler /* OTGHS endpoint1 in */ - .word OTGHS_WKUP_IRQHandler /* OTGHS Wakeup from suspend */ - .word OTGHS_IRQHandler /* OTGHS */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word FPU_IRQHandler /* FPU */ - .word UART7_IRQHandler /* UART7 */ - .word UART8_IRQHandler /* UART8 */ - .word 0 /* Reserved */ - .word I2SF5_IRQHandler /* I2SF5 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word QSPI1_IRQHandler /* QSPI1 */ - .word 0 /* Reserved */ - .word DMAMUX_IRQHandler /* DMAMUX */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word ACC_IRQHandler /* ACC */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDT_IRQHandler - .thumb_set WWDT_IRQHandler,Default_Handler - - .weak PVM_IRQHandler - .thumb_set PVM_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak ERTC_WKUP_IRQHandler - .thumb_set ERTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak CRM_IRQHandler - .thumb_set CRM_IRQHandler,Default_Handler - - .weak EXINT0_IRQHandler - .thumb_set EXINT0_IRQHandler,Default_Handler - - .weak EXINT1_IRQHandler - .thumb_set EXINT1_IRQHandler,Default_Handler - - .weak EXINT2_IRQHandler - .thumb_set EXINT2_IRQHandler,Default_Handler - - .weak EXINT3_IRQHandler - .thumb_set EXINT3_IRQHandler,Default_Handler - - .weak EXINT4_IRQHandler - .thumb_set EXINT4_IRQHandler,Default_Handler - - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - - .weak ADC1_IRQHandler - .thumb_set ADC1_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SE_IRQHandler - .thumb_set CAN1_SE_IRQHandler,Default_Handler - - .weak EXINT9_5_IRQHandler - .thumb_set EXINT9_5_IRQHandler,Default_Handler - - .weak TMR1_BRK_TMR9_IRQHandler - .thumb_set TMR1_BRK_TMR9_IRQHandler,Default_Handler - - .weak TMR1_OVF_TMR10_IRQHandler - .thumb_set TMR1_OVF_TMR10_IRQHandler,Default_Handler - - .weak TMR1_TRG_HALL_TMR11_IRQHandler - .thumb_set TMR1_TRG_HALL_TMR11_IRQHandler,Default_Handler - - .weak TMR1_CH_IRQHandler - .thumb_set TMR1_CH_IRQHandler,Default_Handler - - .weak TMR2_GLOBAL_IRQHandler - .thumb_set TMR2_GLOBAL_IRQHandler,Default_Handler - - .weak TMR3_GLOBAL_IRQHandler - .thumb_set TMR3_GLOBAL_IRQHandler,Default_Handler - - .weak TMR4_GLOBAL_IRQHandler - .thumb_set TMR4_GLOBAL_IRQHandler,Default_Handler - - .weak I2C1_EVT_IRQHandler - .thumb_set I2C1_EVT_IRQHandler,Default_Handler - - .weak I2C1_ERR_IRQHandler - .thumb_set I2C1_ERR_IRQHandler,Default_Handler - - .weak I2C2_EVT_IRQHandler - .thumb_set I2C2_EVT_IRQHandler,Default_Handler - - .weak I2C2_ERR_IRQHandler - .thumb_set I2C2_ERR_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXINT15_10_IRQHandler - .thumb_set EXINT15_10_IRQHandler,Default_Handler - - .weak ERTCAlarm_IRQHandler - .thumb_set ERTCAlarm_IRQHandler,Default_Handler - - .weak OTGFS1_WKUP_IRQHandler - .thumb_set OTGFS1_WKUP_IRQHandler,Default_Handler - - .weak TMR13_GLOBAL_IRQHandler - .thumb_set TMR13_GLOBAL_IRQHandler,Default_Handler - - .weak TMR14_GLOBAL_IRQHandler - .thumb_set TMR14_GLOBAL_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak USART4_IRQHandler - .thumb_set USART4_IRQHandler,Default_Handler - - .weak USART5_IRQHandler - .thumb_set USART5_IRQHandler,Default_Handler - - .weak TMR6_GLOBAL_IRQHandler - .thumb_set TMR6_GLOBAL_IRQHandler,Default_Handler - - .weak TMR7_GLOBAL_IRQHandler - .thumb_set TMR7_GLOBAL_IRQHandler,Default_Handler - - .weak DMA2_Channel1_IRQHandler - .thumb_set DMA2_Channel1_IRQHandler,Default_Handler - - .weak DMA2_Channel2_IRQHandler - .thumb_set DMA2_Channel2_IRQHandler,Default_Handler - - .weak DMA2_Channel3_IRQHandler - .thumb_set DMA2_Channel3_IRQHandler,Default_Handler - - .weak DMA2_Channel4_IRQHandler - .thumb_set DMA2_Channel4_IRQHandler,Default_Handler - - .weak DMA2_Channel5_IRQHandler - .thumb_set DMA2_Channel5_IRQHandler,Default_Handler - - .weak OTGFS1_IRQHandler - .thumb_set OTGFS1_IRQHandler,Default_Handler - - .weak DMA2_Channel6_IRQHandler - .thumb_set DMA2_Channel6_IRQHandler,Default_Handler - - .weak DMA2_Channel7_IRQHandler - .thumb_set DMA2_Channel7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EVT_IRQHandler - .thumb_set I2C3_EVT_IRQHandler,Default_Handler - - .weak I2C3_ERR_IRQHandler - .thumb_set I2C3_ERR_IRQHandler,Default_Handler - - .weak OTGHS_EP1_OUT_IRQHandler - .thumb_set OTGHS_EP1_OUT_IRQHandler,Default_Handler - - .weak OTGHS_EP1_IN_IRQHandler - .thumb_set OTGHS_EP1_IN_IRQHandler,Default_Handler - - .weak OTGHS_WKUP_IRQHandler - .thumb_set OTGHS_WKUP_IRQHandler,Default_Handler - - .weak OTGHS_IRQHandler - .thumb_set OTGHS_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - - .weak UART7_IRQHandler - .thumb_set UART7_IRQHandler,Default_Handler - - .weak UART8_IRQHandler - .thumb_set UART8_IRQHandler,Default_Handler - - .weak I2SF5_IRQHandler - .thumb_set I2SF5_IRQHandler,Default_Handler - - .weak QSPI1_IRQHandler - .thumb_set QSPI1_IRQHandler,Default_Handler - - .weak DMAMUX_IRQHandler - .thumb_set DMAMUX_IRQHandler ,Default_Handler - - .weak ACC_IRQHandler - .thumb_set ACC_IRQHandler,Default_Handler diff --git a/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/AT32F403AxG_FLASH.ld b/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/AT32F403AxG_FLASH.ld deleted file mode 100644 index c3d8aca80..000000000 --- a/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/AT32F403AxG_FLASH.ld +++ /dev/null @@ -1,154 +0,0 @@ -/* -***************************************************************************** -** -** File : AT32F403AxG_FLASH.ld -** -** Abstract : Linker script for AT32F403AxG Device with -** 1000KByte FLASH, 96KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : Artery Tek AT32 -** -** Environment : Arm gcc toolchain -** -***************************************************************************** -*/ - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Highest address of the user mode stack */ -_estack = 0x20018000; /* end of RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0x200; /* required amount of heap */ -_Min_Stack_Size = 0x400; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ -FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K -} - -/* Define output sections */ -SECTIONS -{ - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - /* Constant data goes into FLASH */ - .rodata : - { - . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - . = ALIGN(4); - } >FLASH - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array*)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM AT> FLASH - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss section */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } -} diff --git a/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.cmake b/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.cmake index 72ace807a..25c9558f9 100644 --- a/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.cmake +++ b/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.cmake @@ -1,4 +1,6 @@ set(MCU_VARIANT AT32F403ACGU7) +set(MCU_LINKER_NAME AT32F403AxG) + set(JLINK_DEVICE ${MCU_VARIANT}) function(update_board TARGET) diff --git a/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.mk b/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.mk index e309c86bb..9bb6843aa 100644 --- a/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.mk +++ b/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.mk @@ -1,5 +1,7 @@ -JLINK_DEVICE = at32f403acgu7 -LD_FILE = $(BOARD_PATH)/AT32F403AxG_FLASH.ld +MCU_VARIANT = AT32F403ACGU7 +MCU_LINKER_NAME = AT32F403AxG + +JLINK_DEVICE = ${MCU_VARIANT} CFLAGS += \ - -DAT32F403ACGU7 + -D${MCU_VARIANT} diff --git a/hw/bsp/at32f403a_407/family.cmake b/hw/bsp/at32f403a_407/family.cmake index 19b392015..ae4037088 100644 --- a/hw/bsp/at32f403a_407/family.cmake +++ b/hw/bsp/at32f403a_407/family.cmake @@ -1,9 +1,9 @@ include_guard() -set(AT_FAMILY at32f403a_407) -set(AT_SDK_LIB ${TOP}/hw/mcu/artery/${AT_FAMILY}/libraries) +set(AT32_FAMILY at32f403a_407) +set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries) -string(TOUPPER ${AT_FAMILY} AT_FAMILY_UPPER) +string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER) # include board specific include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) @@ -12,15 +12,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) -set(FAMILY_MCUS ${AT_FAMILY_UPPER} CACHE INTERNAL "") - -# extract variant linker name -string(LENGTH ${MCU_VARIANT} MCU_VARIANT_LEN) -math(EXPR MCU_FLASH_CODE_INDEX "${MCU_VARIANT_LEN} - 3") -math(EXPR MCU_VARIANT_PREFIX_LEN "${MCU_FLASH_CODE_INDEX} - 1") -string(SUBSTRING ${MCU_VARIANT} ${MCU_FLASH_CODE_INDEX} 1 MCU_FLASH_CODE) -string(SUBSTRING ${MCU_VARIANT} 0 ${MCU_VARIANT_PREFIX_LEN} MCU_VARIANT_PREFIX) -set(MCU_LINKER_NAME ${MCU_VARIANT_PREFIX}x${MCU_FLASH_CODE}) +set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") #------------------------------------ # BOARD_TARGET @@ -32,30 +24,30 @@ function(add_board_target BOARD_TARGET) endif () # Startup & Linker script - set(STARTUP_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/startup_${AT_FAMILY}.s) + set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${AT_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT_FAMILY}.s) + set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${AT_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) + set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) endif () set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${AT_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) + set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) add_library(${BOARD_TARGET} STATIC - ${AT_SDK_LIB}/cmsis/cm4/device_support/system_${AT_FAMILY}.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_gpio.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_misc.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_usart.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_acc.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_crm.c + ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${AT_SDK_LIB}/cmsis/cm4/core_support - ${AT_SDK_LIB}/cmsis/cm4/device_support - ${AT_SDK_LIB}/drivers/inc + ${AT32_SDK_LIB}/cmsis/cm4/core_support + ${AT32_SDK_LIB}/cmsis/cm4/device_support + ${AT32_SDK_LIB}/drivers/inc ) update_board(${BOARD_TARGET}) @@ -93,8 +85,8 @@ function(family_configure_example TARGET RTOS) # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT_FAMILY}_clock.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT_FAMILY}_int.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c ) target_include_directories(${TARGET} PUBLIC # family, hw, board @@ -104,7 +96,7 @@ function(family_configure_example TARGET RTOS) ) # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${AT_FAMILY_UPPER}) + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) target_sources(${TARGET} PUBLIC ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c ) diff --git a/hw/bsp/at32f403a_407/family.mk b/hw/bsp/at32f403a_407/family.mk index b3210a6d4..c82d402ca 100644 --- a/hw/bsp/at32f403a_407/family.mk +++ b/hw/bsp/at32f403a_407/family.mk @@ -1,8 +1,5 @@ -# Submodules -AT32F403A_407_SDK = hw/mcu/artery/at32f403a_407 - -# AT32 SDK path -AT32F403A_407_SDK_SRC = $(AT32F403A_407_SDK)/libraries +AT32_FAMILY = at32f403a_407 +AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries include $(TOP)/$(BOARD_PATH)/board.mk @@ -19,21 +16,24 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ - $(AT32F403A_407_SDK_SRC)/drivers/src/at32f403a_407_gpio.c \ - $(AT32F403A_407_SDK_SRC)/drivers/src/at32f403a_407_misc.c \ - $(AT32F403A_407_SDK_SRC)/drivers/src/at32f403a_407_usart.c \ - $(AT32F403A_407_SDK_SRC)/drivers/src/at32f403a_407_acc.c \ - $(AT32F403A_407_SDK_SRC)/drivers/src/at32f403a_407_crm.c \ - $(AT32F403A_407_SDK_SRC)/cmsis/cm4/device_support/system_at32f403a_407.c + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_acc.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \ + $(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(AT32F403A_407_SDK_SRC)/drivers/inc \ - $(TOP)/$(AT32F403A_407_SDK_SRC)/cmsis/cm4/core_support \ - $(TOP)/$(AT32F403A_407_SDK_SRC)/cmsis/cm4/device_support + $(TOP)/$(AT32_SDK_LIB)/drivers/inc \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support -SRC_S += \ - $(FAMILY_PATH)/startup_at32f403a_407.s +SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s +SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s + +LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld +LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf # For freeRTOS port source FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F diff --git a/hw/bsp/at32f403a_407/startup_at32f403a_407.s b/hw/bsp/at32f403a_407/startup_at32f403a_407.s deleted file mode 100644 index 3b81f2043..000000000 --- a/hw/bsp/at32f403a_407/startup_at32f403a_407.s +++ /dev/null @@ -1,478 +0,0 @@ -/** - ****************************************************************************** - * @file startup_at32f403a_407.s - * @brief at32f403a_407xx devices vector table for gcc toolchain. - * this module performs: - * - set the initial sp - * - set the initial pc == reset_handler, - * - set the vector table entries with the exceptions isr address - * - configure the clock system and the external sram to - * be used as data memory (optional, to be enabled by user) - * - branches to main in the c library (which eventually - * calls main()). - * after reset the cortex-m4 processor is in thread mode, - * priority is privileged, and the stack is set to main. - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M3. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDT_IRQHandler /* Window Watchdog Timer */ - .word PVM_IRQHandler /* PVM through EXINT Line detect */ - .word TAMPER_IRQHandler /* Tamper */ - .word RTC_IRQHandler /* RTC */ - .word FLASH_IRQHandler /* Flash */ - .word CRM_IRQHandler /* CRM */ - .word EXINT0_IRQHandler /* EXINT Line 0 */ - .word EXINT1_IRQHandler /* EXINT Line 1 */ - .word EXINT2_IRQHandler /* EXINT Line 2 */ - .word EXINT3_IRQHandler /* EXINT Line 3 */ - .word EXINT4_IRQHandler /* EXINT Line 4 */ - .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ - .word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */ - .word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */ - .word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */ - .word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */ - .word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */ - .word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */ - .word ADC1_2_IRQHandler /* ADC1 & ADC2 */ - .word USBFS_H_CAN1_TX_IRQHandler /* USB High Priority or CAN1 TX */ - .word USBFS_L_CAN1_RX0_IRQHandler /* USB Low Priority or CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SE_IRQHandler /* CAN1 SE */ - .word EXINT9_5_IRQHandler /* EXINT Line [9:5] */ - .word TMR1_BRK_TMR9_IRQHandler /* TMR1 Brake and TMR9 */ - .word TMR1_OVF_TMR10_IRQHandler /* TMR1 Overflow and TMR10 */ - .word TMR1_TRG_HALL_TMR11_IRQHandler /* TMR1 Trigger and hall and TMR11 */ - .word TMR1_CH_IRQHandler /* TMR1 Channel */ - .word TMR2_GLOBAL_IRQHandler /* TMR2 */ - .word TMR3_GLOBAL_IRQHandler /* TMR3 */ - .word TMR4_GLOBAL_IRQHandler /* TMR4 */ - .word I2C1_EVT_IRQHandler /* I2C1 Event */ - .word I2C1_ERR_IRQHandler /* I2C1 Error */ - .word I2C2_EVT_IRQHandler /* I2C2 Event */ - .word I2C2_ERR_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_I2S2EXT_IRQHandler /* SPI2 & I2S2EXT */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXINT15_10_IRQHandler /* EXINT Line [15:10] */ - .word RTCAlarm_IRQHandler /* RTC Alarm through EXINT Line */ - .word USBFSWakeUp_IRQHandler /* USB Wakeup from suspend */ - .word TMR8_BRK_TMR12_IRQHandler /* TMR8 Brake and TMR12 */ - .word TMR8_OVF_TMR13_IRQHandler /* TMR8 Overflow and TMR13 */ - .word TMR8_TRG_HALL_TMR14_IRQHandler /* TMR8 Trigger and hall and TMR14 */ - .word TMR8_CH_IRQHandler /* TMR8 Channel */ - .word ADC3_IRQHandler /* ADC3 */ - .word XMC_IRQHandler /* XMC */ - .word SDIO1_IRQHandler /* SDIO1 */ - .word TMR5_GLOBAL_IRQHandler /* TMR5 */ - .word SPI3_I2S3EXT_IRQHandler /* SPI3 & I2S3EXT */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TMR6_GLOBAL_IRQHandler /* TMR6 */ - .word TMR7_GLOBAL_IRQHandler /* TMR7 */ - .word DMA2_Channel1_IRQHandler /* DMA2 Channel1 */ - .word DMA2_Channel2_IRQHandler /* DMA2 Channel2 */ - .word DMA2_Channel3_IRQHandler /* DMA2 Channel3 */ - .word DMA2_Channel4_5_IRQHandler /* DMA2 Channel4 & Channel5 */ - .word SDIO2_IRQHandler /* SDIO2 */ - .word I2C3_EVT_IRQHandler /* I2C3 Event */ - .word I2C3_ERR_IRQHandler /* I2C3 Error */ - .word SPI4_IRQHandler /* SPI4 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SE_IRQHandler /* CAN2 SE */ - .word ACC_IRQHandler /* ACC */ - .word USBFS_MAPH_IRQHandler /* USB Map HP */ - .word USBFS_MAPL_IRQHandler /* USB Map LP */ - .word DMA2_Channel6_7_IRQHandler /* DMA2 Channel6 & Channel7 */ - .word USART6_IRQHandler /* USART6 */ - .word UART7_IRQHandler /* UART7 */ - .word UART8_IRQHandler /* UART8 */ - .word EMAC_IRQHandler /* EMAC */ - .word EMAC_WKUP_IRQHandler /* EMAC Wakeup */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDT_IRQHandler - .thumb_set WWDT_IRQHandler,Default_Handler - - .weak PVM_IRQHandler - .thumb_set PVM_IRQHandler,Default_Handler - - .weak TAMPER_IRQHandler - .thumb_set TAMPER_IRQHandler,Default_Handler - - .weak RTC_IRQHandler - .thumb_set RTC_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak CRM_IRQHandler - .thumb_set CRM_IRQHandler,Default_Handler - - .weak EXINT0_IRQHandler - .thumb_set EXINT0_IRQHandler,Default_Handler - - .weak EXINT1_IRQHandler - .thumb_set EXINT1_IRQHandler,Default_Handler - - .weak EXINT2_IRQHandler - .thumb_set EXINT2_IRQHandler,Default_Handler - - .weak EXINT3_IRQHandler - .thumb_set EXINT3_IRQHandler,Default_Handler - - .weak EXINT4_IRQHandler - .thumb_set EXINT4_IRQHandler,Default_Handler - - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - - .weak ADC1_2_IRQHandler - .thumb_set ADC1_2_IRQHandler,Default_Handler - - .weak USBFS_H_CAN1_TX_IRQHandler - .thumb_set USBFS_H_CAN1_TX_IRQHandler,Default_Handler - - .weak USBFS_L_CAN1_RX0_IRQHandler - .thumb_set USBFS_L_CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SE_IRQHandler - .thumb_set CAN1_SE_IRQHandler,Default_Handler - - .weak EXINT9_5_IRQHandler - .thumb_set EXINT9_5_IRQHandler,Default_Handler - - .weak TMR1_BRK_TMR9_IRQHandler - .thumb_set TMR1_BRK_TMR9_IRQHandler,Default_Handler - - .weak TMR1_OVF_TMR10_IRQHandler - .thumb_set TMR1_OVF_TMR10_IRQHandler,Default_Handler - - .weak TMR1_TRG_HALL_TMR11_IRQHandler - .thumb_set TMR1_TRG_HALL_TMR11_IRQHandler,Default_Handler - - .weak TMR1_CH_IRQHandler - .thumb_set TMR1_CH_IRQHandler,Default_Handler - - .weak TMR2_GLOBAL_IRQHandler - .thumb_set TMR2_GLOBAL_IRQHandler,Default_Handler - - .weak TMR3_GLOBAL_IRQHandler - .thumb_set TMR3_GLOBAL_IRQHandler,Default_Handler - - .weak TMR4_GLOBAL_IRQHandler - .thumb_set TMR4_GLOBAL_IRQHandler,Default_Handler - - .weak I2C1_EVT_IRQHandler - .thumb_set I2C1_EVT_IRQHandler,Default_Handler - - .weak I2C1_ERR_IRQHandler - .thumb_set I2C1_ERR_IRQHandler,Default_Handler - - .weak I2C2_EVT_IRQHandler - .thumb_set I2C2_EVT_IRQHandler,Default_Handler - - .weak I2C2_ERR_IRQHandler - .thumb_set I2C2_ERR_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_I2S2EXT_IRQHandler - .thumb_set SPI2_I2S2EXT_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXINT15_10_IRQHandler - .thumb_set EXINT15_10_IRQHandler,Default_Handler - - .weak RTCAlarm_IRQHandler - .thumb_set RTCAlarm_IRQHandler,Default_Handler - - .weak USBFSWakeUp_IRQHandler - .thumb_set USBFSWakeUp_IRQHandler,Default_Handler - - .weak TMR8_BRK_TMR12_IRQHandler - .thumb_set TMR8_BRK_TMR12_IRQHandler,Default_Handler - - .weak TMR8_OVF_TMR13_IRQHandler - .thumb_set TMR8_OVF_TMR13_IRQHandler,Default_Handler - - .weak TMR8_TRG_HALL_TMR14_IRQHandler - .thumb_set TMR8_TRG_HALL_TMR14_IRQHandler,Default_Handler - - .weak TMR8_CH_IRQHandler - .thumb_set TMR8_CH_IRQHandler,Default_Handler - - .weak ADC3_IRQHandler - .thumb_set ADC3_IRQHandler,Default_Handler - - .weak XMC_IRQHandler - .thumb_set XMC_IRQHandler,Default_Handler - - .weak SDIO1_IRQHandler - .thumb_set SDIO1_IRQHandler,Default_Handler - - .weak TMR5_GLOBAL_IRQHandler - .thumb_set TMR5_GLOBAL_IRQHandler,Default_Handler - - .weak SPI3_I2S3EXT_IRQHandler - .thumb_set SPI3_I2S3EXT_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TMR6_GLOBAL_IRQHandler - .thumb_set TMR6_GLOBAL_IRQHandler,Default_Handler - - .weak TMR7_GLOBAL_IRQHandler - .thumb_set TMR7_GLOBAL_IRQHandler,Default_Handler - - .weak DMA2_Channel1_IRQHandler - .thumb_set DMA2_Channel1_IRQHandler,Default_Handler - - .weak DMA2_Channel2_IRQHandler - .thumb_set DMA2_Channel2_IRQHandler,Default_Handler - - .weak DMA2_Channel3_IRQHandler - .thumb_set DMA2_Channel3_IRQHandler,Default_Handler - - .weak DMA2_Channel4_5_IRQHandler - .thumb_set DMA2_Channel4_5_IRQHandler,Default_Handler - - .weak SDIO2_IRQHandler - .thumb_set SDIO2_IRQHandler,Default_Handler - - .weak I2C3_EVT_IRQHandler - .thumb_set I2C3_EVT_IRQHandler,Default_Handler - - .weak I2C3_ERR_IRQHandler - .thumb_set I2C3_ERR_IRQHandler,Default_Handler - - .weak SPI4_IRQHandler - .thumb_set SPI4_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler ,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler ,Default_Handler - - .weak CAN2_SE_IRQHandler - .thumb_set CAN2_SE_IRQHandler,Default_Handler - - .weak ACC_IRQHandler - .thumb_set ACC_IRQHandler,Default_Handler - - .weak USBFS_MAPH_IRQHandler - .thumb_set USBFS_MAPH_IRQHandler,Default_Handler - - .weak USBFS_MAPL_IRQHandler - .thumb_set USBFS_MAPL_IRQHandler,Default_Handler - - .weak DMA2_Channel6_7_IRQHandler - .thumb_set DMA2_Channel6_7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak UART7_IRQHandler - .thumb_set UART7_IRQHandler,Default_Handler - - .weak UART8_IRQHandler - .thumb_set UART8_IRQHandler,Default_Handler - - .weak EMAC_IRQHandler - .thumb_set EMAC_IRQHandler,Default_Handler - - .weak EMAC_WKUP_IRQHandler - .thumb_set EMAC_WKUP_IRQHandler,Default_Handler diff --git a/hw/bsp/at32f413/boards/AT_START_F413/AT32F413xC_FLASH.ld b/hw/bsp/at32f413/boards/AT_START_F413/AT32F413xC_FLASH.ld deleted file mode 100644 index 9d95a7d3d..000000000 --- a/hw/bsp/at32f413/boards/AT_START_F413/AT32F413xC_FLASH.ld +++ /dev/null @@ -1,168 +0,0 @@ -/* -***************************************************************************** -** -** File : AT32F413xC_FLASH.ld -** -** Abstract : Linker script for AT32F413xC Device with -** 256KByte FLASH, 32KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : Artery Tek AT32 -** -** Environment : Arm gcc toolchain -** -***************************************************************************** -*/ - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Highest address of the user mode stack */ -_estack = 0x20008000; /* end of RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0x200; /* required amount of heap */ -_Min_Stack_Size = 0x400; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ -FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K -SPIM (rx) : ORIGIN = 0x08400000, LENGTH = 16384K -} - -/* Define output sections */ -SECTIONS -{ - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - /* Constant data goes into FLASH */ - .rodata : - { - . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - . = ALIGN(4); - } >FLASH - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array*)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM AT> FLASH - - _spim_init_base = LOADADDR(.spim); - _spim_init_length = SIZEOF(.spim); - - .spim : - { - . = ALIGN(4); - _spim_start = .; /* create a global symbol at spim start */ - *(.spim) /* .spim sections */ - *(.spim*) /* .spim* sections */ - . = ALIGN(4); - _spim_end = .; /* define a global symbols at end of spim */ - } >SPIM - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss section */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } -} diff --git a/hw/bsp/at32f413/boards/AT_START_F413/board.cmake b/hw/bsp/at32f413/boards/AT_START_F413/board.cmake new file mode 100644 index 000000000..0a9cc4bbd --- /dev/null +++ b/hw/bsp/at32f413/boards/AT_START_F413/board.cmake @@ -0,0 +1,8 @@ +set(MCU_VARIANT AT32F413RCT7) +set(MCU_LINKER_NAME AT32F413xC) + +set(JLINK_DEVICE ${MCU_VARIANT}) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC ${MCU_VARIANT}) +endfunction() diff --git a/hw/bsp/at32f413/boards/AT_START_F413/board.mk b/hw/bsp/at32f413/boards/AT_START_F413/board.mk index 28351265d..30fc6b9af 100644 --- a/hw/bsp/at32f413/boards/AT_START_F413/board.mk +++ b/hw/bsp/at32f413/boards/AT_START_F413/board.mk @@ -1,4 +1,8 @@ -LD_FILE = $(BOARD_PATH)/AT32F413xC_FLASH.ld +MCU_VARIANT = AT32F413RCT7 +MCU_LINKER_NAME = AT32F413xC + +JLINK_DEVICE = ${MCU_VARIANT} CFLAGS += \ - -DAT32F413RCT7 + -D${MCU_VARIANT} \ + -DCFG_EXAMPLE_VIDEO_READONLY diff --git a/hw/bsp/at32f413/family.c b/hw/bsp/at32f413/family.c index ffaf892e7..6e12c6015 100644 --- a/hw/bsp/at32f413/family.c +++ b/hw/bsp/at32f413/family.c @@ -25,8 +25,8 @@ */ #include "at32f413_clock.h" -#include "bsp/board_api.h" #include "board.h" +#include "bsp/board_api.h" void usb_clock48m_select(usb_clk48_s clk_s); void uart_print_init(uint32_t baudrate); @@ -50,8 +50,7 @@ void USBFSWakeUp_IRQHandler(void) { tud_int_handler(0); } -void board_init(void) -{ +void board_init(void) { system_clock_config(); /* config nvic priority group */ @@ -82,7 +81,7 @@ void board_init(void) gpio_default_para_init(&gpio_led_init_struct); /* configure the led gpio */ gpio_led_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_led_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; + gpio_led_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_led_init_struct.gpio_mode = GPIO_MODE_OUTPUT; gpio_led_init_struct.gpio_pins = LED_PIN; gpio_led_init_struct.gpio_pull = GPIO_PULL_NONE; @@ -114,10 +113,8 @@ void board_init(void) * @param clk_s:USB_CLK_HICK, USB_CLK_HEXT * @retval none */ -void usb_clock48m_select(usb_clk48_s clk_s) -{ - if(clk_s == USB_CLK_HICK) - { +void usb_clock48m_select(usb_clk48_s clk_s) { + if (clk_s == USB_CLK_HICK) { crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK); /* enable the acc calibration ready interrupt */ @@ -130,11 +127,8 @@ void usb_clock48m_select(usb_clk48_s clk_s) /* open acc calibration */ acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE); - } - else - { - switch(system_core_clock) - { + } else { + switch (system_core_clock) { /* 48MHz */ case 48000000: crm_usb_clock_div_set(CRM_USB_DIV_1); @@ -176,8 +170,7 @@ void usb_clock48m_select(usb_clk48_s clk_s) } } -void uart_print_init(uint32_t baudrate) -{ +void uart_print_init(uint32_t baudrate) { gpio_init_type gpio_init_struct; /* enable the uart and gpio clock */ crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE); @@ -185,7 +178,7 @@ void uart_print_init(uint32_t baudrate) gpio_default_para_init(&gpio_init_struct); /* configure the uart tx pin */ gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; + gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = PRINT_UART_TX_PIN; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; @@ -206,8 +199,8 @@ uint32_t board_button_read(void) { size_t board_get_unique_id(uint8_t id[], size_t max_len) { (void) max_len; - volatile uint32_t * at32_uuid = ((volatile uint32_t*)0x1FFFF7E8); - uint32_t* id32 = (uint32_t*) (uintptr_t) id; + volatile uint32_t *at32_uuid = ((volatile uint32_t *) 0x1FFFF7E8); + uint32_t *id32 = (uint32_t *) (uintptr_t) id; uint8_t const len = 12; id32[0] = at32_uuid[0]; @@ -223,61 +216,57 @@ int board_uart_read(uint8_t *buf, int len) { return 0; } -int board_uart_write(void const *buf, int len) -{ - #if CFG_TUSB_OS == OPT_OS_NONE - int txsize = len; - u16 timeout = 0xffff; - while (txsize--) - { - while(usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET) - { - timeout--; - if(timeout == 0) - { - return 0; - } +int board_uart_write(void const *buf, int len) { +#if CFG_TUSB_OS == OPT_OS_NONE + int txsize = len; + u16 timeout = 0xffff; + while (txsize--) { + while (usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET) { + timeout--; + if (timeout == 0) { + return 0; } - PRINT_UART->dt = (*((uint8_t const *)buf) & 0x01FF); - buf++; } - return len; - #else - (void) buf; - (void) len; - return 0; - #endif + PRINT_UART->dt = (*((uint8_t const *) buf) & 0x01FF); + buf++; + } + return len; +#else + (void) buf; + (void) len; + return 0; +#endif } #if CFG_TUSB_OS == OPT_OS_NONE - volatile uint32_t system_ticks = 0; - void SysTick_Handler(void) - { - system_ticks++; - } +volatile uint32_t system_ticks = 0; +void SysTick_Handler(void) { + system_ticks++; +} - uint32_t board_millis(void) - { - return system_ticks; - } +uint32_t board_millis(void) { + return system_ticks; +} - void SVC_Handler(void) - { - } +void SVC_Handler(void) { +} - void PendSV_Handler(void) - { - } +void PendSV_Handler(void) { +} #endif void HardFault_Handler(void) { __asm("BKPT #0\n"); } -#ifdef USE_FULL_ASSERT -void assert_failed(const char *file, uint32_t line) -{ +// Required by __libc_init_array in startup code if we are compiling using +// -nostdlib/-nostartfiles. +void _init(void) { +} + +#ifdef USE_FULL_ASSERT +void assert_failed(const char *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ diff --git a/hw/bsp/at32f413/family.cmake b/hw/bsp/at32f413/family.cmake new file mode 100644 index 000000000..b534bcbbc --- /dev/null +++ b/hw/bsp/at32f413/family.cmake @@ -0,0 +1,108 @@ +include_guard() + +set(AT32_FAMILY at32f413) +set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries) + +string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + # Startup & Linker script + set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) + + add_library(${BOARD_TARGET} STATIC + ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${AT32_SDK_LIB}/cmsis/cm4/core_support + ${AT32_SDK_LIB}/cmsis/cm4/device_support + ${AT32_SDK_LIB}/drivers/inc + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + ) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/at32f413/family.mk b/hw/bsp/at32f413/family.mk index cf02445c0..9c5d867de 100644 --- a/hw/bsp/at32f413/family.mk +++ b/hw/bsp/at32f413/family.mk @@ -1,8 +1,5 @@ -# Submodules -AT32F413_SDK = hw/mcu/artery/at32f413 - -# AT32 SDK path -AT32F413_SDK_SRC = $(AT32F413_SDK)/libraries +AT32_FAMILY = at32f413 +AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries include $(TOP)/$(BOARD_PATH)/board.mk @@ -19,21 +16,24 @@ LDFLAGS_GCC += \ SRC_C += \ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \ - $(AT32F413_SDK_SRC)/drivers/src/at32f413_gpio.c \ - $(AT32F413_SDK_SRC)/drivers/src/at32f413_misc.c \ - $(AT32F413_SDK_SRC)/drivers/src/at32f413_usart.c \ - $(AT32F413_SDK_SRC)/drivers/src/at32f413_acc.c \ - $(AT32F413_SDK_SRC)/drivers/src/at32f413_crm.c \ - $(AT32F413_SDK_SRC)/cmsis/cm4/device_support/system_at32f413.c + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_acc.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \ + $(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(AT32F413_SDK_SRC)/drivers/inc \ - $(TOP)/$(AT32F413_SDK_SRC)/cmsis/cm4/core_support \ - $(TOP)/$(AT32F413_SDK_SRC)/cmsis/cm4/device_support + $(TOP)/$(AT32_SDK_LIB)/drivers/inc \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support -SRC_S += \ - $(FAMILY_PATH)/startup_at32f413.s +SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s +SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s + +LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld +LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf # For freeRTOS port source FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F diff --git a/hw/bsp/at32f413/startup_at32f413.s b/hw/bsp/at32f413/startup_at32f413.s deleted file mode 100644 index 42631da93..000000000 --- a/hw/bsp/at32f413/startup_at32f413.s +++ /dev/null @@ -1,431 +0,0 @@ -/** - ****************************************************************************** - * @file startup_at32f413.s - * @brief at32f413xx devices vector table for gcc toolchain. - * this module performs: - * - set the initial sp - * - set the initial pc == reset_handler, - * - set the vector table entries with the exceptions isr address - * - configure the clock system and the external sram to - * be used as data memory (optional, to be enabled by user) - * - branches to main in the c library (which eventually - * calls main()). - * after reset the cortex-m4 processor is in thread mode, - * priority is privileged, and the stack is set to main. - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M3. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDT_IRQHandler /* Window Watchdog Timer */ - .word PVM_IRQHandler /* PVM through EXINT Line detect */ - .word TAMPER_IRQHandler /* Tamper */ - .word RTC_IRQHandler /* RTC */ - .word FLASH_IRQHandler /* Flash */ - .word CRM_IRQHandler /* CRM */ - .word EXINT0_IRQHandler /* EXINT Line 0 */ - .word EXINT1_IRQHandler /* EXINT Line 1 */ - .word EXINT2_IRQHandler /* EXINT Line 2 */ - .word EXINT3_IRQHandler /* EXINT Line 3 */ - .word EXINT4_IRQHandler /* EXINT Line 4 */ - .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ - .word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */ - .word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */ - .word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */ - .word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */ - .word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */ - .word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */ - .word ADC1_2_IRQHandler /* ADC1 & ADC2 */ - .word USBFS_H_CAN1_TX_IRQHandler /* USB High Priority or CAN1 TX */ - .word USBFS_L_CAN1_RX0_IRQHandler /* USB Low Priority or CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SE_IRQHandler /* CAN1 SE */ - .word EXINT9_5_IRQHandler /* EXINT Line [9:5] */ - .word TMR1_BRK_TMR9_IRQHandler /* TMR1 Brake and TMR9 */ - .word TMR1_OVF_TMR10_IRQHandler /* TMR1 Overflow and TMR10 */ - .word TMR1_TRG_HALL_TMR11_IRQHandler /* TMR1 Trigger and hall and TMR11 */ - .word TMR1_CH_IRQHandler /* TMR1 Channel */ - .word TMR2_GLOBAL_IRQHandler /* TMR2 */ - .word TMR3_GLOBAL_IRQHandler /* TMR3 */ - .word TMR4_GLOBAL_IRQHandler /* TMR4 */ - .word I2C1_EVT_IRQHandler /* I2C1 Event */ - .word I2C1_ERR_IRQHandler /* I2C1 Error */ - .word I2C2_EVT_IRQHandler /* I2C2 Event */ - .word I2C2_ERR_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* Reserved */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXINT15_10_IRQHandler /* EXINT Line [15:10] */ - .word RTCAlarm_IRQHandler /* RTC Alarm through EXINT Line */ - .word USBFSWakeUp_IRQHandler /* USB Wakeup from suspend */ - .word TMR8_BRK_IRQHandler /* TMR8 Brake */ - .word TMR8_OVF_IRQHandler /* TMR8 Overflow */ - .word TMR8_TRG_HALL_IRQHandler /* TMR8 Trigger and hall */ - .word TMR8_CH_IRQHandler /* TMR8 Channel */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word SDIO1_IRQHandler /* SDIO1 */ - .word TMR5_GLOBAL_IRQHandler /* TMR5 */ - .word 0 /* Reserved */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word DMA2_Channel1_IRQHandler /* DMA2 Channel1 */ - .word DMA2_Channel2_IRQHandler /* DMA2 Channel2 */ - .word DMA2_Channel3_IRQHandler /* DMA2 Channel3 */ - .word DMA2_Channel4_5_IRQHandler /* DMA2 Channel4 & Channel5 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SE_IRQHandler /* CAN2 SE */ - .word ACC_IRQHandler /* ACC */ - .word USBFS_MAPH_IRQHandler /* USB Map HP */ - .word USBFS_MAPL_IRQHandler /* USB Map LP */ - .word DMA2_Channel6_7_IRQHandler /* DMA2 Channel6 & Channel7 */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDT_IRQHandler - .thumb_set WWDT_IRQHandler,Default_Handler - - .weak PVM_IRQHandler - .thumb_set PVM_IRQHandler,Default_Handler - - .weak TAMPER_IRQHandler - .thumb_set TAMPER_IRQHandler,Default_Handler - - .weak RTC_IRQHandler - .thumb_set RTC_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak CRM_IRQHandler - .thumb_set CRM_IRQHandler,Default_Handler - - .weak EXINT0_IRQHandler - .thumb_set EXINT0_IRQHandler,Default_Handler - - .weak EXINT1_IRQHandler - .thumb_set EXINT1_IRQHandler,Default_Handler - - .weak EXINT2_IRQHandler - .thumb_set EXINT2_IRQHandler,Default_Handler - - .weak EXINT3_IRQHandler - .thumb_set EXINT3_IRQHandler,Default_Handler - - .weak EXINT4_IRQHandler - .thumb_set EXINT4_IRQHandler,Default_Handler - - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - - .weak ADC1_2_IRQHandler - .thumb_set ADC1_2_IRQHandler,Default_Handler - - .weak USBFS_H_CAN1_TX_IRQHandler - .thumb_set USBFS_H_CAN1_TX_IRQHandler,Default_Handler - - .weak USBFS_L_CAN1_RX0_IRQHandler - .thumb_set USBFS_L_CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SE_IRQHandler - .thumb_set CAN1_SE_IRQHandler,Default_Handler - - .weak EXINT9_5_IRQHandler - .thumb_set EXINT9_5_IRQHandler,Default_Handler - - .weak TMR1_BRK_TMR9_IRQHandler - .thumb_set TMR1_BRK_TMR9_IRQHandler,Default_Handler - - .weak TMR1_OVF_TMR10_IRQHandler - .thumb_set TMR1_OVF_TMR10_IRQHandler,Default_Handler - - .weak TMR1_TRG_HALL_TMR11_IRQHandler - .thumb_set TMR1_TRG_HALL_TMR11_IRQHandler,Default_Handler - - .weak TMR1_CH_IRQHandler - .thumb_set TMR1_CH_IRQHandler,Default_Handler - - .weak TMR2_GLOBAL_IRQHandler - .thumb_set TMR2_GLOBAL_IRQHandler,Default_Handler - - .weak TMR3_GLOBAL_IRQHandler - .thumb_set TMR3_GLOBAL_IRQHandler,Default_Handler - - .weak TMR4_GLOBAL_IRQHandler - .thumb_set TMR4_GLOBAL_IRQHandler,Default_Handler - - .weak I2C1_EVT_IRQHandler - .thumb_set I2C1_EVT_IRQHandler,Default_Handler - - .weak I2C1_ERR_IRQHandler - .thumb_set I2C1_ERR_IRQHandler,Default_Handler - - .weak I2C2_EVT_IRQHandler - .thumb_set I2C2_EVT_IRQHandler,Default_Handler - - .weak I2C2_ERR_IRQHandler - .thumb_set I2C2_ERR_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXINT15_10_IRQHandler - .thumb_set EXINT15_10_IRQHandler,Default_Handler - - .weak RTCAlarm_IRQHandler - .thumb_set RTCAlarm_IRQHandler,Default_Handler - - .weak USBFSWakeUp_IRQHandler - .thumb_set USBFSWakeUp_IRQHandler,Default_Handler - - .weak TMR8_BRK_IRQHandler - .thumb_set TMR8_BRK_IRQHandler,Default_Handler - - .weak TMR8_OVF_IRQHandler - .thumb_set TMR8_OVF_IRQHandler,Default_Handler - - .weak TMR8_TRG_HALL_IRQHandler - .thumb_set TMR8_TRG_HALL_IRQHandler,Default_Handler - - .weak TMR8_CH_IRQHandler - .thumb_set TMR8_CH_IRQHandler,Default_Handler - - .weak SDIO1_IRQHandler - .thumb_set SDIO1_IRQHandler,Default_Handler - - .weak TMR5_GLOBAL_IRQHandler - .thumb_set TMR5_GLOBAL_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak DMA2_Channel1_IRQHandler - .thumb_set DMA2_Channel1_IRQHandler,Default_Handler - - .weak DMA2_Channel2_IRQHandler - .thumb_set DMA2_Channel2_IRQHandler,Default_Handler - - .weak DMA2_Channel3_IRQHandler - .thumb_set DMA2_Channel3_IRQHandler,Default_Handler - - .weak DMA2_Channel4_5_IRQHandler - .thumb_set DMA2_Channel4_5_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler ,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler ,Default_Handler - - .weak CAN2_SE_IRQHandler - .thumb_set CAN2_SE_IRQHandler,Default_Handler - - .weak ACC_IRQHandler - .thumb_set ACC_IRQHandler,Default_Handler - - .weak USBFS_MAPH_IRQHandler - .thumb_set USBFS_MAPH_IRQHandler,Default_Handler - - .weak USBFS_MAPL_IRQHandler - .thumb_set USBFS_MAPL_IRQHandler,Default_Handler - - .weak DMA2_Channel6_7_IRQHandler - .thumb_set DMA2_Channel6_7_IRQHandler,Default_Handler diff --git a/hw/bsp/at32f415/boards/AT_START_F415/AT32F415xC_FLASH.ld b/hw/bsp/at32f415/boards/AT_START_F415/AT32F415xC_FLASH.ld deleted file mode 100644 index 6da817705..000000000 --- a/hw/bsp/at32f415/boards/AT_START_F415/AT32F415xC_FLASH.ld +++ /dev/null @@ -1,154 +0,0 @@ -/* -***************************************************************************** -** -** File : AT32F415xC_FLASH.ld -** -** Abstract : Linker script for AT32F415xC Device with -** 256KByte FLASH, 32KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : Artery Tek AT32 -** -** Environment : Arm gcc toolchain -** -***************************************************************************** -*/ - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Highest address of the user mode stack */ -_estack = 0x20008000; /* end of RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0x200; /* required amount of heap */ -_Min_Stack_Size = 0x400; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ -FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K -} - -/* Define output sections */ -SECTIONS -{ - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - /* Constant data goes into FLASH */ - .rodata : - { - . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - . = ALIGN(4); - } >FLASH - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array*)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM AT> FLASH - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss section */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } -} diff --git a/hw/bsp/at32f415/boards/AT_START_F415/board.cmake b/hw/bsp/at32f415/boards/AT_START_F415/board.cmake new file mode 100644 index 000000000..43fc43a70 --- /dev/null +++ b/hw/bsp/at32f415/boards/AT_START_F415/board.cmake @@ -0,0 +1,11 @@ +set(MCU_VARIANT AT32F415RCT7) +set(MCU_LINKER_NAME AT32F415xC) + +set(JLINK_DEVICE ${MCU_VARIANT}) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + ${MCU_VARIANT} + CFG_EXAMPLE_VIDEO_READONLY + ) +endfunction() diff --git a/hw/bsp/at32f415/boards/AT_START_F415/board.mk b/hw/bsp/at32f415/boards/AT_START_F415/board.mk index 6c877ec71..7ea7dc593 100644 --- a/hw/bsp/at32f415/boards/AT_START_F415/board.mk +++ b/hw/bsp/at32f415/boards/AT_START_F415/board.mk @@ -1,4 +1,8 @@ -LD_FILE = $(BOARD_PATH)/AT32F415xC_FLASH.ld +MCU_VARIANT = AT32F415RCT7 +MCU_LINKER_NAME = AT32F415xC + +JLINK_DEVICE = ${MCU_VARIANT} CFLAGS += \ - -DAT32F415RCT7 + -D${MCU_VARIANT} \ + -DCFG_EXAMPLE_VIDEO_READONLY diff --git a/hw/bsp/at32f415/family.c b/hw/bsp/at32f415/family.c index 516095dfb..b8ccae97d 100644 --- a/hw/bsp/at32f415/family.c +++ b/hw/bsp/at32f415/family.c @@ -25,8 +25,8 @@ */ #include "at32f415_clock.h" -#include "bsp/board_api.h" #include "board.h" +#include "bsp/board_api.h" void uart_print_init(uint32_t baudrate); void usb_clock48m_select(usb_clk48_s clk_s); @@ -35,17 +35,14 @@ void led_and_button_init(void); //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void OTGFS1_IRQHandler(void) -{ +void OTGFS1_IRQHandler(void) { tusb_int_handler(0, true); } -void OTGFS1_WKUP_IRQHandler(void) -{ +void OTGFS1_WKUP_IRQHandler(void) { tusb_int_handler(0, true); } -void board_init(void) -{ +void board_init(void) { /* config nvic priority group */ nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); @@ -64,24 +61,24 @@ void board_init(void) /* configure systick */ systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV); SysTick_Config(SystemCoreClock / 1000); - #if CFG_TUSB_OS == OPT_OS_FREERTOS - // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(OTG_IRQ, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); - #endif +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(OTG_IRQ, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif - /* otgfs use vbus pin */ - #ifndef USB_VBUS_IGNORE - gpio_init_type gpio_init_struct; - crm_periph_clock_enable(OTG_PIN_GPIO_CLOCK, TRUE); - gpio_default_para_init(&gpio_init_struct); - gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; - gpio_init_struct.gpio_mode = GPIO_MODE_MUX; - gpio_init_struct.gpio_pins = OTG_PIN_VBUS; - gpio_init_struct.gpio_pull = GPIO_PULL_DOWN; - gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_VBUS_SOURCE, OTG_PIN_MUX); - gpio_init(OTG_PIN_GPIO, &gpio_init_struct); - #endif +/* otgfs use vbus pin */ +#ifndef USB_VBUS_IGNORE + gpio_init_type gpio_init_struct; + crm_periph_clock_enable(OTG_PIN_GPIO_CLOCK, TRUE); + gpio_default_para_init(&gpio_init_struct); + gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; + gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; + gpio_init_struct.gpio_mode = GPIO_MODE_MUX; + gpio_init_struct.gpio_pins = OTG_PIN_VBUS; + gpio_init_struct.gpio_pull = GPIO_PULL_DOWN; + gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_VBUS_SOURCE, OTG_PIN_MUX); + gpio_init(OTG_PIN_GPIO, &gpio_init_struct); +#endif /* config led and key */ led_and_button_init(); @@ -99,43 +96,40 @@ void board_init(void) * @param clk_s:USB_CLK_HICK, USB_CLK_HEXT * @retval none */ -void usb_clock48m_select(usb_clk48_s clk_s) -{ - (void) clk_s; - switch(system_core_clock) - { - /* 48MHz */ - case 48000000: - crm_usb_clock_div_set(CRM_USB_DIV_1); - break; +void usb_clock48m_select(usb_clk48_s clk_s) { + (void) clk_s; + switch (system_core_clock) { + /* 48MHz */ + case 48000000: + crm_usb_clock_div_set(CRM_USB_DIV_1); + break; - /* 72MHz */ - case 72000000: - crm_usb_clock_div_set(CRM_USB_DIV_1_5); - break; + /* 72MHz */ + case 72000000: + crm_usb_clock_div_set(CRM_USB_DIV_1_5); + break; - /* 96MHz */ - case 96000000: - crm_usb_clock_div_set(CRM_USB_DIV_2); - break; + /* 96MHz */ + case 96000000: + crm_usb_clock_div_set(CRM_USB_DIV_2); + break; - /* 120MHz */ - case 120000000: - crm_usb_clock_div_set(CRM_USB_DIV_2_5); - break; + /* 120MHz */ + case 120000000: + crm_usb_clock_div_set(CRM_USB_DIV_2_5); + break; - /* 144MHz */ - case 144000000: - crm_usb_clock_div_set(CRM_USB_DIV_3); - break; + /* 144MHz */ + case 144000000: + crm_usb_clock_div_set(CRM_USB_DIV_3); + break; - default: - break; - } + default: + break; + } } -void led_and_button_init(void) -{ +void led_and_button_init(void) { /* LED */ gpio_init_type gpio_led_init_struct; /* enable the led clock */ @@ -144,7 +138,7 @@ void led_and_button_init(void) gpio_default_para_init(&gpio_led_init_struct); /* configure the led gpio */ gpio_led_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_led_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; + gpio_led_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_led_init_struct.gpio_mode = GPIO_MODE_OUTPUT; gpio_led_init_struct.gpio_pins = LED_PIN; gpio_led_init_struct.gpio_pull = GPIO_PULL_NONE; @@ -169,8 +163,7 @@ void led_and_button_init(void) * @param baudrate: uart baudrate * @retval none */ -void uart_print_init(uint32_t baudrate) -{ +void uart_print_init(uint32_t baudrate) { gpio_init_type gpio_init_struct; /* enable the uart and gpio clock */ crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE); @@ -178,7 +171,7 @@ void uart_print_init(uint32_t baudrate) gpio_default_para_init(&gpio_init_struct); /* configure the uart tx pin */ gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; + gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = PRINT_UART_TX_PIN; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; @@ -190,55 +183,47 @@ void uart_print_init(uint32_t baudrate) } // Get characters from UART. Return number of read bytes -int board_uart_read(uint8_t *buf, int len) -{ +int board_uart_read(uint8_t *buf, int len) { (void) buf; (void) len; return 0; } // 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 - int txsize = len; - u16 timeout = 0xffff; - while (txsize--) - { - while(usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET) - { - timeout--; - if(timeout == 0) - { - return 0; - } +int board_uart_write(void const *buf, int len) { +#if CFG_TUSB_OS == OPT_OS_NONE + int txsize = len; + u16 timeout = 0xffff; + while (txsize--) { + while (usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET) { + timeout--; + if (timeout == 0) { + return 0; } - PRINT_UART->dt = (*((uint8_t const *)buf) & 0x01FF); - buf++; } - return len; - #else - (void) buf; - (void) len; - return 0; - #endif + PRINT_UART->dt = (*((uint8_t const *) buf) & 0x01FF); + buf++; + } + return len; +#else + (void) buf; + (void) len; + return 0; +#endif } -void board_led_write(bool state) -{ +void board_led_write(bool state) { gpio_bits_write(LED_PORT, LED_PIN, state ^ (!LED_STATE_ON)); } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { return gpio_input_data_bit_read(BUTTON_PORT, BUTTON_PIN); } -size_t board_get_unique_id(uint8_t id[], size_t max_len) -{ +size_t board_get_unique_id(uint8_t id[], size_t max_len) { (void) max_len; - volatile uint32_t * at32_uuid = ((volatile uint32_t*)0x1FFFF7E8); - uint32_t* id32 = (uint32_t*) (uintptr_t) id; + volatile uint32_t *at32_uuid = ((volatile uint32_t *) 0x1FFFF7E8); + uint32_t *id32 = (uint32_t *) (uintptr_t) id; uint8_t const len = 12; id32[0] = at32_uuid[0]; @@ -251,24 +236,20 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) #if CFG_TUSB_OS == OPT_OS_NONE - volatile uint32_t system_ticks = 0; - void SysTick_Handler(void) - { - system_ticks++; - } +volatile uint32_t system_ticks = 0; +void SysTick_Handler(void) { + system_ticks++; +} - uint32_t board_millis(void) - { - return system_ticks; - } +uint32_t board_millis(void) { + return system_ticks; +} - void SVC_Handler(void) - { - } +void SVC_Handler(void) { +} - void PendSV_Handler(void) - { - } +void PendSV_Handler(void) { +} #endif void HardFault_Handler(void) { @@ -280,9 +261,8 @@ void HardFault_Handler(void) { void _init(void) { } -#ifdef USE_FULL_ASSERT -void assert_failed(const char *file, uint32_t line) -{ +#ifdef USE_FULL_ASSERT +void assert_failed(const char *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ diff --git a/hw/bsp/at32f415/family.cmake b/hw/bsp/at32f415/family.cmake new file mode 100644 index 000000000..8ac946265 --- /dev/null +++ b/hw/bsp/at32f415/family.cmake @@ -0,0 +1,108 @@ +include_guard() + +set(AT32_FAMILY at32f415) +set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries) + +string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m4-nofpu CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + # Startup & Linker script + set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) + + add_library(${BOARD_TARGET} STATIC + ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${AT32_SDK_LIB}/cmsis/cm4/core_support + ${AT32_SDK_LIB}/cmsis/cm4/device_support + ${AT32_SDK_LIB}/drivers/inc + ) + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/at32f415/family.mk b/hw/bsp/at32f415/family.mk index 1edf6be4e..73a89c543 100644 --- a/hw/bsp/at32f415/family.mk +++ b/hw/bsp/at32f415/family.mk @@ -1,12 +1,9 @@ -# Submodules -AT32F415_SDK = hw/mcu/artery/at32f415 - -# AT32 SDK path -AT32F415_SDK_SRC = $(AT32F415_SDK)/libraries +AT32_FAMILY = at32f415 +AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries include $(TOP)/$(BOARD_PATH)/board.mk -CPU_CORE ?= cortex-m3 +CPU_CORE ?= cortex-m4-nofpu CFLAGS_GCC += \ -flto @@ -21,22 +18,22 @@ SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ src/portable/synopsys/dwc2/hcd_dwc2.c \ src/portable/synopsys/dwc2/dwc2_common.c \ - $(AT32F415_SDK_SRC)/drivers/src/at32f415_gpio.c \ - $(AT32F415_SDK_SRC)/drivers/src/at32f415_misc.c \ - $(AT32F415_SDK_SRC)/drivers/src/at32f415_usart.c \ - $(AT32F415_SDK_SRC)/drivers/src/at32f415_crm.c \ - $(AT32F415_SDK_SRC)/cmsis/cm4/device_support/system_at32f415.c + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \ + $(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(AT32F415_SDK_SRC)/drivers/inc \ - $(TOP)/$(AT32F415_SDK_SRC)/cmsis/cm4/core_support \ - $(TOP)/$(AT32F415_SDK_SRC)/cmsis/cm4/device_support + $(TOP)/$(AT32_SDK_LIB)/drivers/inc \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support -SRC_S += \ - $(FAMILY_PATH)/startup_at32f415.s +SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s +SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s -# For freeRTOS port source -#FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4 +LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld +LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf flash: flash-atlink diff --git a/hw/bsp/at32f415/startup_at32f415.s b/hw/bsp/at32f415/startup_at32f415.s deleted file mode 100644 index 2c4dbc9ef..000000000 --- a/hw/bsp/at32f415/startup_at32f415.s +++ /dev/null @@ -1,407 +0,0 @@ -/** - ****************************************************************************** - * @file startup_at32f415.s - * @brief at32f415xx devices vector table for gcc toolchain. - * this module performs: - * - set the initial sp - * - set the initial pc == reset_handler, - * - set the vector table entries with the exceptions isr address - * - configure the clock system and the external sram to - * be used as data memory (optional, to be enabled by user) - * - branches to main in the c library (which eventually - * calls main()). - * after reset the cortex-m4 processor is in thread mode, - * priority is privileged, and the stack is set to main. - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M3. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDT_IRQHandler /* Window Watchdog Timer */ - .word PVM_IRQHandler /* PVM through EXINT Line detect */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXINT line */ - .word ERTC_WKUP_IRQHandler /* ERTC Wakeup through the EXINT line */ - .word FLASH_IRQHandler /* Flash */ - .word CRM_IRQHandler /* CRM */ - .word EXINT0_IRQHandler /* EXINT Line 0 */ - .word EXINT1_IRQHandler /* EXINT Line 1 */ - .word EXINT2_IRQHandler /* EXINT Line 2 */ - .word EXINT3_IRQHandler /* EXINT Line 3 */ - .word EXINT4_IRQHandler /* EXINT Line 4 */ - .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ - .word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */ - .word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */ - .word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */ - .word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */ - .word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */ - .word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */ - .word ADC1_IRQHandler /* ADC1 */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SE_IRQHandler /* CAN1 SE */ - .word EXINT9_5_IRQHandler /* EXINT Line [9:5] */ - .word TMR1_BRK_TMR9_IRQHandler /* TMR1 Brake and TMR9 */ - .word TMR1_OVF_TMR10_IRQHandler /* TMR1 overflow and TMR10 */ - .word TMR1_TRG_HALL_TMR11_IRQHandler /* TMR1 Trigger and hall and TMR11 */ - .word TMR1_CH_IRQHandler /* TMR1 channel */ - .word TMR2_GLOBAL_IRQHandler /* TMR2 */ - .word TMR3_GLOBAL_IRQHandler /* TMR3 */ - .word TMR4_GLOBAL_IRQHandler /* TMR4 */ - .word I2C1_EVT_IRQHandler /* I2C1 Event */ - .word I2C1_ERR_IRQHandler /* I2C1 Error */ - .word I2C2_EVT_IRQHandler /* I2C2 Event */ - .word I2C2_ERR_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXINT15_10_IRQHandler /* EXINT Line [15:10] */ - .word ERTCAlarm_IRQHandler /* ERTC Alarm through EXINT Line */ - .word OTGFS1_WKUP_IRQHandler /* OTGFS1 Wakeup from suspend */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word SDIO1_IRQHandler /* SDIO1 */ - .word TMR5_GLOBAL_IRQHandler /* TMR5 */ - .word 0 /* Reserved */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word DMA2_Channel1_IRQHandler /* DMA2 Channel1 */ - .word DMA2_Channel2_IRQHandler /* DMA2 Channel2 */ - .word DMA2_Channel3_IRQHandler /* DMA2 Channel3 */ - .word DMA2_Channel4_5_IRQHandler /* DMA2 Channel4 & Channel5 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word OTGFS1_IRQHandler /* OTGFS1 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word CMP1_IRQHandler /* CMP1 */ - .word CMP2_IRQHandler /* CMP2 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word DMA2_Channel6_7_IRQHandler /* DMA2 Channel6 & Channel7 */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDT_IRQHandler - .thumb_set WWDT_IRQHandler,Default_Handler - - .weak PVM_IRQHandler - .thumb_set PVM_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak ERTC_WKUP_IRQHandler - .thumb_set ERTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak CRM_IRQHandler - .thumb_set CRM_IRQHandler,Default_Handler - - .weak EXINT0_IRQHandler - .thumb_set EXINT0_IRQHandler,Default_Handler - - .weak EXINT1_IRQHandler - .thumb_set EXINT1_IRQHandler,Default_Handler - - .weak EXINT2_IRQHandler - .thumb_set EXINT2_IRQHandler,Default_Handler - - .weak EXINT3_IRQHandler - .thumb_set EXINT3_IRQHandler,Default_Handler - - .weak EXINT4_IRQHandler - .thumb_set EXINT4_IRQHandler,Default_Handler - - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - - .weak ADC1_IRQHandler - .thumb_set ADC1_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SE_IRQHandler - .thumb_set CAN1_SE_IRQHandler,Default_Handler - - .weak EXINT9_5_IRQHandler - .thumb_set EXINT9_5_IRQHandler,Default_Handler - - .weak TMR1_BRK_TMR9_IRQHandler - .thumb_set TMR1_BRK_TMR9_IRQHandler,Default_Handler - - .weak TMR1_OVF_TMR10_IRQHandler - .thumb_set TMR1_OVF_TMR10_IRQHandler,Default_Handler - - .weak TMR1_TRG_HALL_TMR11_IRQHandler - .thumb_set TMR1_TRG_HALL_TMR11_IRQHandler,Default_Handler - - .weak TMR1_CH_IRQHandler - .thumb_set TMR1_CH_IRQHandler,Default_Handler - - .weak TMR2_GLOBAL_IRQHandler - .thumb_set TMR2_GLOBAL_IRQHandler,Default_Handler - - .weak TMR3_GLOBAL_IRQHandler - .thumb_set TMR3_GLOBAL_IRQHandler,Default_Handler - - .weak TMR4_GLOBAL_IRQHandler - .thumb_set TMR4_GLOBAL_IRQHandler,Default_Handler - - .weak I2C1_EVT_IRQHandler - .thumb_set I2C1_EVT_IRQHandler,Default_Handler - - .weak I2C1_ERR_IRQHandler - .thumb_set I2C1_ERR_IRQHandler,Default_Handler - - .weak I2C2_EVT_IRQHandler - .thumb_set I2C2_EVT_IRQHandler,Default_Handler - - .weak I2C2_ERR_IRQHandler - .thumb_set I2C2_ERR_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXINT15_10_IRQHandler - .thumb_set EXINT15_10_IRQHandler,Default_Handler - - .weak ERTCAlarm_IRQHandler - .thumb_set ERTCAlarm_IRQHandler,Default_Handler - - .weak OTGFS1_WKUP_IRQHandler - .thumb_set OTGFS1_WKUP_IRQHandler,Default_Handler - - .weak SDIO1_IRQHandler - .thumb_set SDIO1_IRQHandler,Default_Handler - - .weak TMR5_GLOBAL_IRQHandler - .thumb_set TMR5_GLOBAL_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak DMA2_Channel1_IRQHandler - .thumb_set DMA2_Channel1_IRQHandler,Default_Handler - - .weak DMA2_Channel2_IRQHandler - .thumb_set DMA2_Channel2_IRQHandler,Default_Handler - - .weak DMA2_Channel3_IRQHandler - .thumb_set DMA2_Channel3_IRQHandler,Default_Handler - - .weak DMA2_Channel4_5_IRQHandler - .thumb_set DMA2_Channel4_5_IRQHandler,Default_Handler - - .weak OTGFS1_IRQHandler - .thumb_set OTGFS1_IRQHandler,Default_Handler - - .weak CMP1_IRQHandler - .thumb_set CMP1_IRQHandler,Default_Handler - - .weak CMP2_IRQHandler - .thumb_set CMP2_IRQHandler,Default_Handler - - .weak DMA2_Channel6_7_IRQHandler - .thumb_set DMA2_Channel6_7_IRQHandler,Default_Handler diff --git a/hw/bsp/at32f423/boards/AT_START_F423/AT32F423xC_FLASH.ld b/hw/bsp/at32f423/boards/AT_START_F423/AT32F423xC_FLASH.ld deleted file mode 100644 index ee08e979a..000000000 --- a/hw/bsp/at32f423/boards/AT_START_F423/AT32F423xC_FLASH.ld +++ /dev/null @@ -1,154 +0,0 @@ -/* -***************************************************************************** -** -** File : AT32F423xC_FLASH.ld -** -** Abstract : Linker script for AT32F423xC Device with -** 256KByte FLASH, 48KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : Artery Tek AT32 -** -** Environment : Arm gcc toolchain -** -***************************************************************************** -*/ - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Highest address of the user mode stack */ -_estack = 0x2000C000; /* end of RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0x200; /* required amount of heap */ -_Min_Stack_Size = 0x400; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ -FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K -} - -/* Define output sections */ -SECTIONS -{ - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - /* Constant data goes into FLASH */ - .rodata : - { - . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - . = ALIGN(4); - } >FLASH - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array*)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM AT> FLASH - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss section */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } -} diff --git a/hw/bsp/at32f423/boards/AT_START_F423/board.cmake b/hw/bsp/at32f423/boards/AT_START_F423/board.cmake index 45aa39900..f97a12194 100644 --- a/hw/bsp/at32f423/boards/AT_START_F423/board.cmake +++ b/hw/bsp/at32f423/boards/AT_START_F423/board.cmake @@ -1,4 +1,6 @@ set(MCU_VARIANT AT32F423VCT7) +set(MCU_LINKER_NAME AT32F423xC) + set(JLINK_DEVICE ${MCU_VARIANT}) function(update_board TARGET) diff --git a/hw/bsp/at32f423/boards/AT_START_F423/board.mk b/hw/bsp/at32f423/boards/AT_START_F423/board.mk index 4c19c81bb..f7ef2117d 100644 --- a/hw/bsp/at32f423/boards/AT_START_F423/board.mk +++ b/hw/bsp/at32f423/boards/AT_START_F423/board.mk @@ -1,5 +1,7 @@ -JLINK_DEVICE = AT32F423VCT7 -LD_FILE = $(BOARD_PATH)/AT32F423xC_FLASH.ld +MCU_VARIANT = AT32F423VCT7 +MCU_LINKER_NAME = AT32F423xC + +JLINK_DEVICE = ${MCU_VARIANT} CFLAGS += \ - -DAT32F423VCT7 + -D${MCU_VARIANT} diff --git a/hw/bsp/at32f423/family.cmake b/hw/bsp/at32f423/family.cmake index 3845f13ad..17c3f37a2 100644 --- a/hw/bsp/at32f423/family.cmake +++ b/hw/bsp/at32f423/family.cmake @@ -1,9 +1,9 @@ include_guard() -set(AT_FAMILY at32f423) -set(AT_SDK_LIB ${TOP}/hw/mcu/artery/${AT_FAMILY}/libraries) +set(AT32_FAMILY at32f423) +set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries) -string(TOUPPER ${AT_FAMILY} AT_FAMILY_UPPER) +string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER) # include board specific include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) @@ -12,15 +12,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) -set(FAMILY_MCUS ${AT_FAMILY_UPPER} CACHE INTERNAL "") - -# extract variant linker name -string(LENGTH ${MCU_VARIANT} MCU_VARIANT_LEN) -math(EXPR MCU_FLASH_CODE_INDEX "${MCU_VARIANT_LEN} - 3") -math(EXPR MCU_VARIANT_PREFIX_LEN "${MCU_FLASH_CODE_INDEX} - 1") -string(SUBSTRING ${MCU_VARIANT} ${MCU_FLASH_CODE_INDEX} 1 MCU_FLASH_CODE) -string(SUBSTRING ${MCU_VARIANT} 0 ${MCU_VARIANT_PREFIX_LEN} MCU_VARIANT_PREFIX) -set(MCU_LINKER_NAME ${MCU_VARIANT_PREFIX}x${MCU_FLASH_CODE}) +set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") #------------------------------------ # BOARD_TARGET @@ -32,30 +24,30 @@ function(add_board_target BOARD_TARGET) endif () # Startup & Linker script - set(STARTUP_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/startup_${AT_FAMILY}.s) + set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) - set(STARTUP_FILE_IAR ${AT_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT_FAMILY}.s) + set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) if (NOT DEFINED LD_FILE_GNU) - set(LD_FILE_GNU ${AT_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) + set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) endif () set(LD_FILE_Clang ${LD_FILE_GNU}) - set(LD_FILE_IAR ${AT_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) + set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) add_library(${BOARD_TARGET} STATIC - ${AT_SDK_LIB}/cmsis/cm4/device_support/system_${AT_FAMILY}.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_gpio.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_misc.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_usart.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_acc.c - ${AT_SDK_LIB}/drivers/src/${AT_FAMILY}_crm.c + ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC ${CMAKE_CURRENT_FUNCTION_LIST_DIR} - ${AT_SDK_LIB}/cmsis/cm4/core_support - ${AT_SDK_LIB}/cmsis/cm4/device_support - ${AT_SDK_LIB}/drivers/inc + ${AT32_SDK_LIB}/cmsis/cm4/core_support + ${AT32_SDK_LIB}/cmsis/cm4/device_support + ${AT32_SDK_LIB}/drivers/inc ) update_board(${BOARD_TARGET}) @@ -93,8 +85,8 @@ function(family_configure_example TARGET RTOS) # BSP ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT_FAMILY}_clock.c - ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT_FAMILY}_int.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c ) target_include_directories(${TARGET} PUBLIC # family, hw, board @@ -104,7 +96,7 @@ function(family_configure_example TARGET RTOS) ) # Add TinyUSB target and port source - family_add_tinyusb(${TARGET} OPT_MCU_${AT_FAMILY_UPPER}) + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) target_sources(${TARGET} PUBLIC ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c diff --git a/hw/bsp/at32f423/family.mk b/hw/bsp/at32f423/family.mk index 8ee1072be..960f4a9a1 100644 --- a/hw/bsp/at32f423/family.mk +++ b/hw/bsp/at32f423/family.mk @@ -1,9 +1,5 @@ -JLINK_DEVICE = AT32F423VCT7 - -AT32F423_SDK = hw/mcu/artery/at32f423 - -# AT32 SDK path -AT32F423_SDK_SRC = $(AT32F423_SDK)/libraries +AT32_FAMILY = at32f423 +AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries include $(TOP)/$(BOARD_PATH)/board.mk @@ -22,23 +18,23 @@ SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ src/portable/synopsys/dwc2/hcd_dwc2.c \ src/portable/synopsys/dwc2/dwc2_common.c \ - $(AT32F423_SDK_SRC)/drivers/src/at32f423_gpio.c \ - $(AT32F423_SDK_SRC)/drivers/src/at32f423_misc.c \ - $(AT32F423_SDK_SRC)/drivers/src/at32f423_usart.c \ - $(AT32F423_SDK_SRC)/drivers/src/at32f423_crm.c \ - $(AT32F423_SDK_SRC)/drivers/src/at32f423_acc.c \ - $(AT32F423_SDK_SRC)/cmsis/cm4/device_support/system_at32f423.c + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_acc.c \ + $(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(AT32F423_SDK_SRC)/drivers/inc \ - $(TOP)/$(AT32F423_SDK_SRC)/cmsis/cm4/core_support \ - $(TOP)/$(AT32F423_SDK_SRC)/cmsis/cm4/device_support + $(TOP)/$(AT32_SDK_LIB)/drivers/inc \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support -SRC_S += \ - $(FAMILY_PATH)/startup_at32f423.s +SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s +SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s -# For freeRTOS port source -#FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4 +LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld +LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf flash: flash-atlink diff --git a/hw/bsp/at32f423/startup_at32f423.s b/hw/bsp/at32f423/startup_at32f423.s deleted file mode 100644 index 3e5404009..000000000 --- a/hw/bsp/at32f423/startup_at32f423.s +++ /dev/null @@ -1,483 +0,0 @@ -/** - ****************************************************************************** - * @file startup_at32f423.s - * @brief at32f423 devices vector table for gcc toolchain. - * this module performs: - * - set the initial sp - * - set the initial pc == reset_handler, - * - set the vector table entries with the exceptions isr address - * - configure the clock system and the external sram to - * be used as data memory (optional, to be enabled by user) - * - branches to main in the c library (which eventually - * calls main()). - * after reset the cortex-m4 processor is in thread mode, - * priority is privileged, and the stack is set to main. - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M3. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDT_IRQHandler /* Window Watchdog Timer */ - .word PVM_IRQHandler /* PVM through EXINT Line detect */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXINT line */ - .word ERTC_WKUP_IRQHandler /* ERTC Wakeup through the EXINT line */ - .word FLASH_IRQHandler /* Flash */ - .word CRM_IRQHandler /* CRM */ - .word EXINT0_IRQHandler /* EXINT Line 0 */ - .word EXINT1_IRQHandler /* EXINT Line 1 */ - .word EXINT2_IRQHandler /* EXINT Line 2 */ - .word EXINT3_IRQHandler /* EXINT Line 3 */ - .word EXINT4_IRQHandler /* EXINT Line 4 */ - .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ - .word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */ - .word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */ - .word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */ - .word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */ - .word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */ - .word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */ - .word ADC1_IRQHandler /* ADC1 */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SE_IRQHandler /* CAN1 SE */ - .word EXINT9_5_IRQHandler /* EXINT Line [9:5] */ - .word TMR1_BRK_TMR9_IRQHandler /* TMR1 Brake and TMR9 */ - .word TMR1_OVF_TMR10_IRQHandler /* TMR1 Overflow and TMR10 */ - .word TMR1_TRG_HALL_TMR11_IRQHandler /* TMR1 Trigger and hall and TMR11 */ - .word TMR1_CH_IRQHandler /* TMR1 Channel */ - .word TMR2_GLOBAL_IRQHandler /* TMR2 */ - .word TMR3_GLOBAL_IRQHandler /* TMR3 */ - .word TMR4_GLOBAL_IRQHandler /* TMR4 */ - .word I2C1_EVT_IRQHandler /* I2C1 Event */ - .word I2C1_ERR_IRQHandler /* I2C1 Error */ - .word I2C2_EVT_IRQHandler /* I2C2 Event */ - .word I2C2_ERR_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXINT15_10_IRQHandler /* EXINT Line [15:10] */ - .word ERTCAlarm_IRQHandler /* RTC Alarm through EXINT Line */ - .word OTGFS1_WKUP_IRQHandler /* OTGFS1 Wakeup from suspend */ - .word TMR12_GLOBAL_IRQHandler /* TMR12 */ - .word TMR13_GLOBAL_IRQHandler /* TMR13 */ - .word TMR14_GLOBAL_IRQHandler /* TMR14 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word SPI3_IRQHandler /* SPI3 */ - .word USART4_IRQHandler /* USART4 */ - .word USART5_IRQHandler /* USART5 */ - .word TMR6_DAC_GLOBAL_IRQHandler /* TMR6 & DAC */ - .word TMR7_GLOBAL_IRQHandler /* TMR7 */ - .word DMA2_Channel1_IRQHandler /* DMA2 Channel 1 */ - .word DMA2_Channel2_IRQHandler /* DMA2 Channel 2 */ - .word DMA2_Channel3_IRQHandler /* DMA2 Channel 3 */ - .word DMA2_Channel4_IRQHandler /* DMA2 Channel 4 */ - .word DMA2_Channel5_IRQHandler /* DMA2 Channel 5 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SE_IRQHandler /* CAN2 SE */ - .word OTGFS1_IRQHandler /* OTGFS1 */ - .word DMA2_Channel6_IRQHandler /* DMA2 Channel 6 */ - .word DMA2_Channel7_IRQHandler /* DMA2 Channel 7 */ - .word 0 /* Reserved */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EVT_IRQHandler /* I2C3 Event */ - .word I2C3_ERR_IRQHandler /* I2C3 Error */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word FPU_IRQHandler /* FPU */ - .word USART7_IRQHandler /* USART7 */ - .word USART8_IRQHandler /* USART8 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word DMAMUX_IRQHandler /* DMAMUX */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word ACC_IRQHandler /* ACC */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDT_IRQHandler - .thumb_set WWDT_IRQHandler,Default_Handler - - .weak PVM_IRQHandler - .thumb_set PVM_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak ERTC_WKUP_IRQHandler - .thumb_set ERTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak CRM_IRQHandler - .thumb_set CRM_IRQHandler,Default_Handler - - .weak EXINT0_IRQHandler - .thumb_set EXINT0_IRQHandler,Default_Handler - - .weak EXINT1_IRQHandler - .thumb_set EXINT1_IRQHandler,Default_Handler - - .weak EXINT2_IRQHandler - .thumb_set EXINT2_IRQHandler,Default_Handler - - .weak EXINT3_IRQHandler - .thumb_set EXINT3_IRQHandler,Default_Handler - - .weak EXINT4_IRQHandler - .thumb_set EXINT4_IRQHandler,Default_Handler - - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - - .weak ADC1_IRQHandler - .thumb_set ADC1_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SE_IRQHandler - .thumb_set CAN1_SE_IRQHandler,Default_Handler - - .weak EXINT9_5_IRQHandler - .thumb_set EXINT9_5_IRQHandler,Default_Handler - - .weak TMR1_BRK_TMR9_IRQHandler - .thumb_set TMR1_BRK_TMR9_IRQHandler,Default_Handler - - .weak TMR1_OVF_TMR10_IRQHandler - .thumb_set TMR1_OVF_TMR10_IRQHandler,Default_Handler - - .weak TMR1_TRG_HALL_TMR11_IRQHandler - .thumb_set TMR1_TRG_HALL_TMR11_IRQHandler,Default_Handler - - .weak TMR1_CH_IRQHandler - .thumb_set TMR1_CH_IRQHandler,Default_Handler - - .weak TMR2_GLOBAL_IRQHandler - .thumb_set TMR2_GLOBAL_IRQHandler,Default_Handler - - .weak TMR3_GLOBAL_IRQHandler - .thumb_set TMR3_GLOBAL_IRQHandler,Default_Handler - - .weak TMR4_GLOBAL_IRQHandler - .thumb_set TMR4_GLOBAL_IRQHandler,Default_Handler - - .weak I2C1_EVT_IRQHandler - .thumb_set I2C1_EVT_IRQHandler,Default_Handler - - .weak I2C1_ERR_IRQHandler - .thumb_set I2C1_ERR_IRQHandler,Default_Handler - - .weak I2C2_EVT_IRQHandler - .thumb_set I2C2_EVT_IRQHandler,Default_Handler - - .weak I2C2_ERR_IRQHandler - .thumb_set I2C2_ERR_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXINT15_10_IRQHandler - .thumb_set EXINT15_10_IRQHandler,Default_Handler - - .weak ERTCAlarm_IRQHandler - .thumb_set ERTCAlarm_IRQHandler,Default_Handler - - .weak OTGFS1_WKUP_IRQHandler - .thumb_set OTGFS1_WKUP_IRQHandler,Default_Handler - - .weak TMR12_GLOBAL_IRQHandler - .thumb_set TMR12_GLOBAL_IRQHandler,Default_Handler - - .weak TMR13_GLOBAL_IRQHandler - .thumb_set TMR13_GLOBAL_IRQHandler,Default_Handler - - .weak TMR14_GLOBAL_IRQHandler - .thumb_set TMR14_GLOBAL_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak USART4_IRQHandler - .thumb_set USART4_IRQHandler,Default_Handler - - .weak USART5_IRQHandler - .thumb_set USART5_IRQHandler,Default_Handler - - .weak TMR6_DAC_GLOBAL_IRQHandler - .thumb_set TMR6_DAC_GLOBAL_IRQHandler,Default_Handler - - .weak TMR7_GLOBAL_IRQHandler - .thumb_set TMR7_GLOBAL_IRQHandler,Default_Handler - - .weak DMA2_Channel1_IRQHandler - .thumb_set DMA2_Channel1_IRQHandler,Default_Handler - - .weak DMA2_Channel2_IRQHandler - .thumb_set DMA2_Channel2_IRQHandler,Default_Handler - - .weak DMA2_Channel3_IRQHandler - .thumb_set DMA2_Channel3_IRQHandler,Default_Handler - - .weak DMA2_Channel4_IRQHandler - .thumb_set DMA2_Channel4_IRQHandler,Default_Handler - - .weak DMA2_Channel5_IRQHandler - .thumb_set DMA2_Channel5_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler ,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler ,Default_Handler - - .weak CAN2_SE_IRQHandler - .thumb_set CAN2_SE_IRQHandler,Default_Handler - - .weak OTGFS1_IRQHandler - .thumb_set OTGFS1_IRQHandler,Default_Handler - - .weak DMA2_Channel6_IRQHandler - .thumb_set DMA2_Channel6_IRQHandler,Default_Handler - - .weak DMA2_Channel7_IRQHandler - .thumb_set DMA2_Channel7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EVT_IRQHandler - .thumb_set I2C3_EVT_IRQHandler,Default_Handler - - .weak I2C3_ERR_IRQHandler - .thumb_set I2C3_ERR_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - - .weak USART7_IRQHandler - .thumb_set USART7_IRQHandler,Default_Handler - - .weak USART8_IRQHandler - .thumb_set USART8_IRQHandler,Default_Handler - - .weak DMAMUX_IRQHandler - .thumb_set DMAMUX_IRQHandler ,Default_Handler - - .weak ACC_IRQHandler - .thumb_set ACC_IRQHandler,Default_Handler diff --git a/hw/bsp/at32f425/boards/AT_START_F425/AT32F425x8_FLASH.ld b/hw/bsp/at32f425/boards/AT_START_F425/AT32F425x8_FLASH.ld deleted file mode 100644 index b1d767b51..000000000 --- a/hw/bsp/at32f425/boards/AT_START_F425/AT32F425x8_FLASH.ld +++ /dev/null @@ -1,153 +0,0 @@ -/* -***************************************************************************** -** -** File : AT32F425x8_FLASH.ld -** -** Abstract : Linker script for AT32F425x8 Device with -** 64KByte FLASH, 16KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** -** Environment : Arm gcc toolchain -** -***************************************************************************** -*/ - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Highest address of the user mode stack */ -_estack = 0x20005000; /* end of RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0x200; /* required amount of heap */ -_Min_Stack_Size = 0x400; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ -FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K -} - -/* Define output sections */ -SECTIONS -{ - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - /* Constant data goes into FLASH */ - .rodata : - { - . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - . = ALIGN(4); - } >FLASH - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array*)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM AT> FLASH - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss section */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } -} diff --git a/hw/bsp/at32f425/boards/AT_START_F425/board.cmake b/hw/bsp/at32f425/boards/AT_START_F425/board.cmake new file mode 100644 index 000000000..535bb3cb4 --- /dev/null +++ b/hw/bsp/at32f425/boards/AT_START_F425/board.cmake @@ -0,0 +1,12 @@ +set(MCU_VARIANT AT32F425R8T7) +set(MCU_LINKER_NAME AT32F425x8) + +set(JLINK_DEVICE ${MCU_VARIANT}) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + ${MCU_VARIANT} + CFG_EXAMPLE_VIDEO_READONLY + CFG_EXAMPLE_MSC_READONLY + ) +endfunction() diff --git a/hw/bsp/at32f425/boards/AT_START_F425/board.mk b/hw/bsp/at32f425/boards/AT_START_F425/board.mk index 3fa74d95a..f7aeba1db 100644 --- a/hw/bsp/at32f425/boards/AT_START_F425/board.mk +++ b/hw/bsp/at32f425/boards/AT_START_F425/board.mk @@ -1,4 +1,9 @@ -LD_FILE = $(BOARD_PATH)/AT32F425x8_FLASH.ld +MCU_VARIANT = AT32F425R8T7 +MCU_LINKER_NAME = AT32F425x8 + +JLINK_DEVICE = ${MCU_VARIANT} CFLAGS += \ - -DAT32F425R8T7 + -D${MCU_VARIANT} \ + -DCFG_EXAMPLE_VIDEO_READONLY \ + -DCFG_EXAMPLE_MSC_READONLY diff --git a/hw/bsp/at32f425/family.c b/hw/bsp/at32f425/family.c index 59a485210..26e69bf31 100644 --- a/hw/bsp/at32f425/family.c +++ b/hw/bsp/at32f425/family.c @@ -25,8 +25,8 @@ */ #include "at32f425_clock.h" -#include "bsp/board_api.h" #include "board.h" +#include "bsp/board_api.h" void uart_print_init(uint32_t baudrate); void usb_clock48m_select(usb_clk48_s clk_s); @@ -35,17 +35,14 @@ void led_and_button_init(void); //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void OTGFS1_IRQHandler(void) -{ +void OTGFS1_IRQHandler(void) { tusb_int_handler(0, true); } -void OTGFS1_WKUP_IRQHandler(void) -{ +void OTGFS1_WKUP_IRQHandler(void) { tusb_int_handler(0, true); } -void board_init(void) -{ +void board_init(void) { /* config nvic priority group */ nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); @@ -64,24 +61,24 @@ void board_init(void) /* configure systick */ systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV); SysTick_Config(SystemCoreClock / 1000); - #if CFG_TUSB_OS == OPT_OS_FREERTOS - // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(OTG_IRQ, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); - #endif +#if CFG_TUSB_OS == OPT_OS_FREERTOS + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(OTG_IRQ, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#endif - /* otgfs use vbus pin */ - #ifndef USB_VBUS_IGNORE - gpio_init_type gpio_init_struct; - crm_periph_clock_enable(OTG_PIN_GPIO_CLOCK, TRUE); - gpio_default_para_init(&gpio_init_struct); - gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; - gpio_init_struct.gpio_mode = GPIO_MODE_MUX; - gpio_init_struct.gpio_pins = OTG_PIN_VBUS; - gpio_init_struct.gpio_pull = GPIO_PULL_DOWN; - gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_VBUS_SOURCE, OTG_PIN_MUX); - gpio_init(OTG_PIN_GPIO, &gpio_init_struct); - #endif +/* otgfs use vbus pin */ +#ifndef USB_VBUS_IGNORE + gpio_init_type gpio_init_struct; + crm_periph_clock_enable(OTG_PIN_GPIO_CLOCK, TRUE); + gpio_default_para_init(&gpio_init_struct); + gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; + gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; + gpio_init_struct.gpio_mode = GPIO_MODE_MUX; + gpio_init_struct.gpio_pins = OTG_PIN_VBUS; + gpio_init_struct.gpio_pull = GPIO_PULL_DOWN; + gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_VBUS_SOURCE, OTG_PIN_MUX); + gpio_init(OTG_PIN_GPIO, &gpio_init_struct); +#endif /* config led and key */ led_and_button_init(); @@ -99,10 +96,8 @@ void board_init(void) * @param clk_s:USB_CLK_HICK, USB_CLK_HEXT * @retval none */ -void usb_clock48m_select(usb_clk48_s clk_s) -{ - if(clk_s == USB_CLK_HICK) - { +void usb_clock48m_select(usb_clk48_s clk_s) { + if (clk_s == USB_CLK_HICK) { crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK); /* enable the acc calibration ready interrupt */ @@ -115,14 +110,11 @@ void usb_clock48m_select(usb_clk48_s clk_s) /* open acc calibration */ acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE); - } - else - { - /* usb divider reset */ + } else { + /* usb divider reset */ crm_usb_div_reset(); - switch(system_core_clock) - { + switch (system_core_clock) { /* 48MHz */ case 48000000: crm_usb_clock_div_set(CRM_USB_DIV_1); @@ -144,8 +136,7 @@ void usb_clock48m_select(usb_clk48_s clk_s) } } -void led_and_button_init(void) -{ +void led_and_button_init(void) { /* LED */ gpio_init_type gpio_led_init_struct; /* enable the led clock */ @@ -154,7 +145,7 @@ void led_and_button_init(void) gpio_default_para_init(&gpio_led_init_struct); /* configure the led gpio */ gpio_led_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_led_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; + gpio_led_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_led_init_struct.gpio_mode = GPIO_MODE_OUTPUT; gpio_led_init_struct.gpio_pins = LED_PIN; gpio_led_init_struct.gpio_pull = GPIO_PULL_NONE; @@ -179,8 +170,7 @@ void led_and_button_init(void) * @param baudrate: uart baudrate * @retval none */ -void uart_print_init(uint32_t baudrate) -{ +void uart_print_init(uint32_t baudrate) { gpio_init_type gpio_init_struct; /* enable the uart and gpio clock */ crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE); @@ -188,7 +178,7 @@ void uart_print_init(uint32_t baudrate) gpio_default_para_init(&gpio_init_struct); /* configure the uart tx pin */ gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; + gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = PRINT_UART_TX_PIN; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; @@ -201,55 +191,47 @@ void uart_print_init(uint32_t baudrate) } // Get characters from UART. Return number of read bytes -int board_uart_read(uint8_t *buf, int len) -{ +int board_uart_read(uint8_t *buf, int len) { (void) buf; (void) len; return 0; } // 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 - int txsize = len; - u16 timeout = 0xffff; - while (txsize--) - { - while(usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET) - { - timeout--; - if(timeout == 0) - { - return 0; - } +int board_uart_write(void const *buf, int len) { +#if CFG_TUSB_OS == OPT_OS_NONE + int txsize = len; + u16 timeout = 0xffff; + while (txsize--) { + while (usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET) { + timeout--; + if (timeout == 0) { + return 0; } - PRINT_UART->dt = (*((uint8_t const *)buf) & 0x01FF); - buf++; } - return len; - #else - (void) buf; - (void) len; - return 0; - #endif + PRINT_UART->dt = (*((uint8_t const *) buf) & 0x01FF); + buf++; + } + return len; +#else + (void) buf; + (void) len; + return 0; +#endif } -void board_led_write(bool state) -{ +void board_led_write(bool state) { gpio_bits_write(LED_PORT, LED_PIN, state ^ (!LED_STATE_ON)); } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { return gpio_input_data_bit_read(BUTTON_PORT, BUTTON_PIN); } -size_t board_get_unique_id(uint8_t id[], size_t max_len) -{ +size_t board_get_unique_id(uint8_t id[], size_t max_len) { (void) max_len; - volatile uint32_t * at32_uuid = ((volatile uint32_t*)0x1FFFF7E8); - uint32_t* id32 = (uint32_t*) (uintptr_t) id; + volatile uint32_t *at32_uuid = ((volatile uint32_t *) 0x1FFFF7E8); + uint32_t *id32 = (uint32_t *) (uintptr_t) id; uint8_t const len = 12; id32[0] = at32_uuid[0]; @@ -262,24 +244,20 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) #if CFG_TUSB_OS == OPT_OS_NONE - volatile uint32_t system_ticks = 0; - void SysTick_Handler(void) - { - system_ticks++; - } +volatile uint32_t system_ticks = 0; +void SysTick_Handler(void) { + system_ticks++; +} - uint32_t board_millis(void) - { - return system_ticks; - } +uint32_t board_millis(void) { + return system_ticks; +} - void SVC_Handler(void) - { - } +void SVC_Handler(void) { +} - void PendSV_Handler(void) - { - } +void PendSV_Handler(void) { +} #endif void HardFault_Handler(void) { @@ -291,9 +269,8 @@ void HardFault_Handler(void) { void _init(void) { } -#ifdef USE_FULL_ASSERT -void assert_failed(const char *file, uint32_t line) -{ +#ifdef USE_FULL_ASSERT +void assert_failed(const char *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ diff --git a/hw/bsp/at32f425/family.cmake b/hw/bsp/at32f425/family.cmake new file mode 100644 index 000000000..3f6b36a6b --- /dev/null +++ b/hw/bsp/at32f425/family.cmake @@ -0,0 +1,108 @@ +include_guard() + +set(AT32_FAMILY at32f425) +set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries) + +string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m4-nofpu CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + # Startup & Linker script + set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) + + add_library(${BOARD_TARGET} STATIC + ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${AT32_SDK_LIB}/cmsis/cm4/core_support + ${AT32_SDK_LIB}/cmsis/cm4/device_support + ${AT32_SDK_LIB}/drivers/inc + ) + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/at32f425/family.mk b/hw/bsp/at32f425/family.mk index 81d5ffc97..0a0a74414 100644 --- a/hw/bsp/at32f425/family.mk +++ b/hw/bsp/at32f425/family.mk @@ -1,12 +1,9 @@ -# Submodules -AT32F425_SDK = hw/mcu/artery/at32f425 - -# AT32 SDK path -AT32F425_SDK_SRC = $(AT32F425_SDK)/libraries +AT32_FAMILY = at32f425 +AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries include $(TOP)/$(BOARD_PATH)/board.mk -CPU_CORE ?= cortex-m3 +CPU_CORE ?= cortex-m4-nofpu CFLAGS_GCC += \ -flto @@ -21,22 +18,22 @@ SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ src/portable/synopsys/dwc2/hcd_dwc2.c \ src/portable/synopsys/dwc2/dwc2_common.c \ - $(AT32F425_SDK_SRC)/drivers/src/at32f425_gpio.c \ - $(AT32F425_SDK_SRC)/drivers/src/at32f425_misc.c \ - $(AT32F425_SDK_SRC)/drivers/src/at32f425_usart.c \ - $(AT32F425_SDK_SRC)/drivers/src/at32f425_crm.c \ - $(AT32F425_SDK_SRC)/cmsis/cm4/device_support/system_at32f425.c + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \ + $(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(AT32F425_SDK_SRC)/drivers/inc \ - $(TOP)/$(AT32F425_SDK_SRC)/cmsis/cm4/core_support \ - $(TOP)/$(AT32F425_SDK_SRC)/cmsis/cm4/device_support + $(TOP)/$(AT32_SDK_LIB)/drivers/inc \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support -SRC_S += \ - $(FAMILY_PATH)/startup_at32f425.s +SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s +SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s -# For freeRTOS port source -#FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4 +LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld +LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf flash: flash-atlink diff --git a/hw/bsp/at32f425/startup_at32f425.s b/hw/bsp/at32f425/startup_at32f425.s deleted file mode 100644 index d41fd3f42..000000000 --- a/hw/bsp/at32f425/startup_at32f425.s +++ /dev/null @@ -1,309 +0,0 @@ -/** - ****************************************************************************** - * @file startup_at32f425.s - * @brief at32f425xx devices vector table for gcc toolchain. - * this module performs: - * - set the initial sp - * - set the initial pc == reset_handler, - * - set the vector table entries with the exceptions isr address - * - configure the clock system and the external sram to - * be used as data memory (optional, to be enabled by user) - * - branches to main in the c library (which eventually - * calls main()). - * after reset the cortex-m4 processor is in thread mode, - * priority is privileged, and the stack is set to main. - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M3. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDT_IRQHandler /* Window Watchdog Timer */ - .word PVM_IRQHandler /* PVM through EXINT Line detect */ - .word ERTC_IRQHandler /* ERTC */ - .word FLASH_IRQHandler /* Flash */ - .word CRM_IRQHandler /* CRM */ - .word EXINT1_0_IRQHandler /* EXINT Line 1 & 0 */ - .word EXINT3_2_IRQHandler /* EXINT Line 3 & 2 */ - .word EXINT15_4_IRQHandler /* EXINT Line 15 ~ 4 */ - .word ACC_IRQHandler /* ACC */ - .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ - .word DMA1_Channel3_2_IRQHandler /* DMA1 Channel 3 & 2 */ - .word DMA1_Channel7_4_IRQHandler /* DMA1 Channel 7 & 4 */ - .word ADC1_IRQHandler /* ADC1 */ - .word TMR1_BRK_OVF_TRG_HALL_IRQHandler /* TMR1 brake overflow trigger and hall */ - .word TMR1_CH_IRQHandler /* TMR1 channel */ - .word TMR2_GLOBAL_IRQHandler /* TMR2 */ - .word TMR3_GLOBAL_IRQHandler /* TMR3 */ - .word TMR6_GLOBAL_IRQHandler /* TMR6 */ - .word TMR7_GLOBAL_IRQHandler /* TMR7 */ - .word TMR14_GLOBAL_IRQHandler /* TMR14 */ - .word TMR15_GLOBAL_IRQHandler /* TMR15 */ - .word TMR16_GLOBAL_IRQHandler /* TMR16 */ - .word TMR17_GLOBAL_IRQHandler /* TMR17 */ - .word I2C1_EVT_IRQHandler /* I2C1 Event */ - .word I2C2_EVT_IRQHandler /* I2C2 Event */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART4_3_IRQHandler /* USART3 & USART4 */ - .word CAN1_IRQHandler /* CAN1 */ - .word OTGFS1_IRQHandler /* OTGFS1 */ - .word I2C1_ERR_IRQHandler /* I2C1 Error */ - .word SPI3_IRQHandler /* SPI3 */ - .word I2C2_ERR_IRQHandler /* I2C2 Error */ - .word TMR13_GLOBAL_IRQHandler /* TMR13 */ -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDT_IRQHandler - .thumb_set WWDT_IRQHandler,Default_Handler - - .weak PVM_IRQHandler - .thumb_set PVM_IRQHandler,Default_Handler - - .weak ERTC_IRQHandler - .thumb_set ERTC_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak CRM_IRQHandler - .thumb_set CRM_IRQHandler,Default_Handler - - .weak EXINT1_0_IRQHandler - .thumb_set EXINT1_0_IRQHandler,Default_Handler - - .weak EXINT3_2_IRQHandler - .thumb_set EXINT3_2_IRQHandler,Default_Handler - - .weak EXINT15_4_IRQHandler - .thumb_set EXINT15_4_IRQHandler,Default_Handler - - .weak ACC_IRQHandler - .thumb_set ACC_IRQHandler,Default_Handler - - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel3_2_IRQHandler - .thumb_set DMA1_Channel3_2_IRQHandler,Default_Handler - - .weak DMA1_Channel7_4_IRQHandler - .thumb_set DMA1_Channel7_4_IRQHandler,Default_Handler - - .weak ADC1_IRQHandler - .thumb_set ADC1_IRQHandler,Default_Handler - - .weak TMR1_BRK_OVF_TRG_HALL_IRQHandler - .thumb_set TMR1_BRK_OVF_TRG_HALL_IRQHandler,Default_Handler - - .weak TMR1_CH_IRQHandler - .thumb_set TMR1_CH_IRQHandler,Default_Handler - - .weak TMR2_GLOBAL_IRQHandler - .thumb_set TMR2_GLOBAL_IRQHandler,Default_Handler - - .weak TMR3_GLOBAL_IRQHandler - .thumb_set TMR3_GLOBAL_IRQHandler,Default_Handler - - .weak TMR6_GLOBAL_IRQHandler - .thumb_set TMR6_GLOBAL_IRQHandler,Default_Handler - - .weak TMR7_GLOBAL_IRQHandler - .thumb_set TMR7_GLOBAL_IRQHandler,Default_Handler - - .weak TMR14_GLOBAL_IRQHandler - .thumb_set TMR14_GLOBAL_IRQHandler,Default_Handler - - .weak TMR15_GLOBAL_IRQHandler - .thumb_set TMR15_GLOBAL_IRQHandler,Default_Handler - - .weak TMR16_GLOBAL_IRQHandler - .thumb_set TMR16_GLOBAL_IRQHandler,Default_Handler - - .weak TMR17_GLOBAL_IRQHandler - .thumb_set TMR17_GLOBAL_IRQHandler,Default_Handler - - .weak I2C1_EVT_IRQHandler - .thumb_set I2C1_EVT_IRQHandler,Default_Handler - - .weak I2C2_EVT_IRQHandler - .thumb_set I2C2_EVT_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_IRQHandler - .thumb_set SPI2_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART4_3_IRQHandler - .thumb_set USART4_3_IRQHandler,Default_Handler - - .weak CAN1_IRQHandler - .thumb_set CAN1_IRQHandler,Default_Handler - - .weak OTGFS1_IRQHandler - .thumb_set OTGFS1_IRQHandler,Default_Handler - - .weak I2C1_ERR_IRQHandler - .thumb_set I2C1_ERR_IRQHandler,Default_Handler - - .weak SPI3_IRQHandler - .thumb_set SPI3_IRQHandler,Default_Handler - - .weak I2C2_ERR_IRQHandler - .thumb_set I2C2_ERR_IRQHandler,Default_Handler - - .weak TMR13_GLOBAL_IRQHandler - .thumb_set TMR13_GLOBAL_IRQHandler,Default_Handler diff --git a/hw/bsp/at32f435_437/boards/AT_START_F435_437/AT32F437xM_FLASH.ld b/hw/bsp/at32f435_437/boards/AT_START_F435_437/AT32F437xM_FLASH.ld deleted file mode 100644 index b9d5ba223..000000000 --- a/hw/bsp/at32f435_437/boards/AT_START_F435_437/AT32F437xM_FLASH.ld +++ /dev/null @@ -1,154 +0,0 @@ -/* -***************************************************************************** -** -** File : AT32F437xM_FLASH.ld -** -** Abstract : Linker script for AT32F437xM Device with -** 4096KByte FLASH, 384KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : Artery Tek AT32 -** -** Environment : Arm gcc toolchain -** -***************************************************************************** -*/ - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Highest address of the user mode stack */ -_estack = 0x20060000; /* end of RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0x200; /* required amount of heap */ -_Min_Stack_Size = 0x400; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ -FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 4032K -RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 384K -} - -/* Define output sections */ -SECTIONS -{ - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - /* Constant data goes into FLASH */ - .rodata : - { - . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - . = ALIGN(4); - } >FLASH - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array*)) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM AT> FLASH - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss section */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } -} diff --git a/hw/bsp/at32f435_437/boards/AT_START_F435_437/board.cmake b/hw/bsp/at32f435_437/boards/AT_START_F435_437/board.cmake new file mode 100644 index 000000000..fc54dbcab --- /dev/null +++ b/hw/bsp/at32f435_437/boards/AT_START_F435_437/board.cmake @@ -0,0 +1,8 @@ +set(MCU_VARIANT AT32F437ZMT7) +set(MCU_LINKER_NAME AT32F437xM) + +set(JLINK_DEVICE ${MCU_VARIANT}) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC ${MCU_VARIANT}) +endfunction() diff --git a/hw/bsp/at32f435_437/boards/AT_START_F435_437/board.mk b/hw/bsp/at32f435_437/boards/AT_START_F435_437/board.mk index 823ae677d..e663d59f0 100644 --- a/hw/bsp/at32f435_437/boards/AT_START_F435_437/board.mk +++ b/hw/bsp/at32f435_437/boards/AT_START_F435_437/board.mk @@ -1,4 +1,7 @@ -LD_FILE = $(BOARD_PATH)/AT32F437xM_FLASH.ld +MCU_VARIANT = AT32F437ZMT7 +MCU_LINKER_NAME = AT32F437xM + +JLINK_DEVICE = ${MCU_VARIANT} CFLAGS += \ - -DAT32F437ZMT7 + -D${MCU_VARIANT} diff --git a/hw/bsp/at32f435_437/family.c b/hw/bsp/at32f435_437/family.c index af1fb30e0..c93beeb5a 100644 --- a/hw/bsp/at32f435_437/family.c +++ b/hw/bsp/at32f435_437/family.c @@ -25,8 +25,8 @@ */ #include "at32f435_437_clock.h" -#include "bsp/board_api.h" #include "board.h" +#include "bsp/board_api.h" void usb_gpio_config(void); void uart_print_init(uint32_t baudrate); @@ -36,25 +36,20 @@ int inHandlerMode(void); //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void OTGFS1_IRQHandler(void) -{ +void OTGFS1_IRQHandler(void) { tusb_int_handler(0, true); } -void OTGFS2_IRQHandler(void) -{ +void OTGFS2_IRQHandler(void) { tusb_int_handler(1, true); } -void OTGFS1_WKUP_IRQHandler(void) -{ +void OTGFS1_WKUP_IRQHandler(void) { tusb_int_handler(0, true); } -void OTGFS2_WKUP_IRQHandler(void) -{ +void OTGFS2_WKUP_IRQHandler(void) { tusb_int_handler(1, true); } -void board_init(void) -{ +void board_init(void) { /* config nvic priority group */ nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); @@ -97,10 +92,8 @@ void board_init(void) * @param clk_s:USB_CLK_HICK, USB_CLK_HEXT * @retval none */ -void usb_clock48m_select(usb_clk48_s clk_s) -{ - if(clk_s == USB_CLK_HICK) - { +void usb_clock48m_select(usb_clk48_s clk_s) { + if (clk_s == USB_CLK_HICK) { crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK); /* enable the acc calibration ready interrupt */ @@ -110,20 +103,17 @@ void usb_clock48m_select(usb_clk48_s clk_s) acc_write_c1(7980); acc_write_c2(8000); acc_write_c3(8020); - #ifdef BOARD_TUD_RHPORT - #if BOARD_TUD_RHPORT == 0 - acc_sof_select(ACC_SOF_OTG1); - #else - acc_sof_select(ACC_SOF_OTG2); - #endif - #endif +#ifdef BOARD_TUD_RHPORT + #if BOARD_TUD_RHPORT == 0 + acc_sof_select(ACC_SOF_OTG1); + #else + acc_sof_select(ACC_SOF_OTG2); + #endif +#endif /* open acc calibration */ acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE); - } - else - { - switch(system_core_clock) - { + } else { + switch (system_core_clock) { /* 48MHz */ case 48000000: crm_usb_clock_div_set(CRM_USB_DIV_1); @@ -185,8 +175,7 @@ void usb_clock48m_select(usb_clk48_s clk_s) } } -void led_and_botton_init(void) -{ +void led_and_botton_init(void) { /* LED */ gpio_init_type gpio_led_init_struct; /* enable the led clock */ @@ -195,7 +184,7 @@ void led_and_botton_init(void) gpio_default_para_init(&gpio_led_init_struct); /* configure the led gpio */ gpio_led_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_led_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; + gpio_led_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_led_init_struct.gpio_mode = GPIO_MODE_OUTPUT; gpio_led_init_struct.gpio_pins = LED_PIN; gpio_led_init_struct.gpio_pull = GPIO_PULL_NONE; @@ -223,8 +212,7 @@ void led_and_botton_init(void) * @param baudrate: uart baudrate * @retval none */ -void uart_print_init(uint32_t baudrate) -{ +void uart_print_init(uint32_t baudrate) { gpio_init_type gpio_init_struct; /* enable the uart and gpio clock */ crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE); @@ -232,7 +220,7 @@ void uart_print_init(uint32_t baudrate) gpio_default_para_init(&gpio_init_struct); /* configure the uart tx pin */ gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; + gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = PRINT_UART_TX_PIN; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; @@ -245,51 +233,44 @@ void uart_print_init(uint32_t baudrate) } // Get characters from UART. Return number of read bytes -int board_uart_read(uint8_t *buf, int len) -{ +int board_uart_read(uint8_t *buf, int len) { (void) buf; (void) len; return 0; } // 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 - int txsize = len; - u16 timeout = 0xffff; - while (txsize--) - { - while(usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET) - { - timeout--; - if(timeout == 0) - { - return 0; - } +int board_uart_write(void const *buf, int len) { +#if CFG_TUSB_OS == OPT_OS_NONE + int txsize = len; + u16 timeout = 0xffff; + while (txsize--) { + while (usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET) { + timeout--; + if (timeout == 0) { + return 0; } - PRINT_UART->dt = (*((uint8_t const *)buf) & 0x01FF); - buf++; } - return len; - #else - (void) buf; - (void) len; - return 0; - #endif + PRINT_UART->dt = (*((uint8_t const *) buf) & 0x01FF); + buf++; + } + return len; +#else + (void) buf; + (void) len; + return 0; +#endif } -int inHandlerMode(void) -{ - return __get_IPSR(); +int inHandlerMode(void) { + return __get_IPSR(); } -void usb_gpio_config(void) -{ +void usb_gpio_config(void) { gpio_init_type gpio_init_struct; crm_periph_clock_enable(OTG_PIN_GPIO_CLOCK, TRUE); gpio_default_para_init(&gpio_init_struct); gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; + gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; /* dp and dm */ @@ -297,36 +278,33 @@ void usb_gpio_config(void) gpio_init(OTG_PIN_GPIO, &gpio_init_struct); gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_DP_SOURCE, OTG_PIN_MUX); gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_DM_SOURCE, OTG_PIN_MUX); - #ifdef USB_SOF_OUTPUT_ENABLE - crm_periph_clock_enable(OTG_PIN_SOF_GPIO_CLOCK, TRUE); - gpio_init_struct.gpio_pins = OTG_PIN_SOF; - gpio_init(OTG_PIN_SOF_GPIO, &gpio_init_struct); - gpio_pin_mux_config(OTG_PIN_SOF_GPIO, OTG_PIN_SOF_SOURCE, OTG_PIN_MUX); - #endif - /* otgfs use vbus pin */ - #ifndef USB_VBUS_IGNORE - gpio_init_struct.gpio_pins = OTG_PIN_VBUS; - gpio_init_struct.gpio_pull = GPIO_PULL_DOWN; - gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_VBUS_SOURCE, OTG_PIN_MUX); - gpio_init(OTG_PIN_GPIO, &gpio_init_struct); - #endif +#ifdef USB_SOF_OUTPUT_ENABLE + crm_periph_clock_enable(OTG_PIN_SOF_GPIO_CLOCK, TRUE); + gpio_init_struct.gpio_pins = OTG_PIN_SOF; + gpio_init(OTG_PIN_SOF_GPIO, &gpio_init_struct); + gpio_pin_mux_config(OTG_PIN_SOF_GPIO, OTG_PIN_SOF_SOURCE, OTG_PIN_MUX); +#endif + /* otgfs use vbus pin */ +#ifndef USB_VBUS_IGNORE + gpio_init_struct.gpio_pins = OTG_PIN_VBUS; + gpio_init_struct.gpio_pull = GPIO_PULL_DOWN; + gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_VBUS_SOURCE, OTG_PIN_MUX); + gpio_init(OTG_PIN_GPIO, &gpio_init_struct); +#endif } -void board_led_write(bool state) -{ +void board_led_write(bool state) { gpio_bits_write(LED_PORT, LED_PIN, state ^ (!LED_STATE_ON)); } -uint32_t board_button_read(void) -{ +uint32_t board_button_read(void) { return gpio_input_data_bit_read(BUTTON_PORT, BUTTON_PIN); } -size_t board_get_unique_id(uint8_t id[], size_t max_len) -{ +size_t board_get_unique_id(uint8_t id[], size_t max_len) { (void) max_len; - volatile uint32_t * at32_uuid = ((volatile uint32_t*)0x1FFFF7E8); - uint32_t* id32 = (uint32_t*) (uintptr_t) id; + volatile uint32_t *at32_uuid = ((volatile uint32_t *) 0x1FFFF7E8); + uint32_t *id32 = (uint32_t *) (uintptr_t) id; uint8_t const len = 12; id32[0] = at32_uuid[0]; @@ -337,21 +315,17 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) } #if CFG_TUSB_OS == OPT_OS_NONE - volatile uint32_t system_ticks = 0; - void SysTick_Handler(void) - { - system_ticks++; - } - uint32_t board_millis(void) - { - return system_ticks; - } - void SVC_Handler(void) - { - } - void PendSV_Handler(void) - { - } +volatile uint32_t system_ticks = 0; +void SysTick_Handler(void) { + system_ticks++; +} +uint32_t board_millis(void) { + return system_ticks; +} +void SVC_Handler(void) { +} +void PendSV_Handler(void) { +} #endif void HardFault_Handler(void) { @@ -363,9 +337,8 @@ void HardFault_Handler(void) { void _init(void) { } -#ifdef USE_FULL_ASSERT -void assert_failed(const char *file, uint32_t line) -{ +#ifdef USE_FULL_ASSERT +void assert_failed(const char *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ diff --git a/hw/bsp/at32f435_437/family.cmake b/hw/bsp/at32f435_437/family.cmake new file mode 100644 index 000000000..c85b58ae4 --- /dev/null +++ b/hw/bsp/at32f435_437/family.cmake @@ -0,0 +1,114 @@ +include_guard() + +set(AT32_FAMILY at32f435_437) +set(AT32_SDK_LIB ${TOP}/hw/mcu/artery/${AT32_FAMILY}/libraries) + +string(TOUPPER ${AT32_FAMILY} AT32_FAMILY_UPPER) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m4 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif () + + # Startup & Linker script + set(STARTUP_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + set(STARTUP_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s) + + if (NOT DEFINED LD_FILE_GNU) + set(LD_FILE_GNU ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld) + endif () + set(LD_FILE_Clang ${LD_FILE_GNU}) + set(LD_FILE_IAR ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf) + + add_library(${BOARD_TARGET} STATIC + ${AT32_SDK_LIB}/cmsis/cm4/device_support/system_${AT32_FAMILY}.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_gpio.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_misc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_usart.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_acc.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_crm.c + ${AT32_SDK_LIB}/drivers/src/${AT32_FAMILY}_exint.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${AT32_SDK_LIB}/cmsis/cm4/core_support + ${AT32_SDK_LIB}/cmsis/cm4/device_support + ${AT32_SDK_LIB}/drivers/inc + ) + target_compile_definitions(${BOARD_TARGET} PUBLIC + BOARD_TUD_RHPORT=0 + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_${AT32_FAMILY_UPPER}) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/at32f435_437/family.mk b/hw/bsp/at32f435_437/family.mk index 891c7501c..b33be1180 100644 --- a/hw/bsp/at32f435_437/family.mk +++ b/hw/bsp/at32f435_437/family.mk @@ -1,8 +1,5 @@ -# Submodules -AT32F435_437_SDK = hw/mcu/artery/at32f435_437 - -# AT32 SDK path -AT32F435_437_SDK_SRC = $(AT32F435_437_SDK)/libraries +AT32_FAMILY = at32f435_437 +AT32_SDK_LIB = hw/mcu/artery/${AT32_FAMILY}/libraries include $(TOP)/$(BOARD_PATH)/board.mk @@ -13,6 +10,7 @@ CFLAGS_GCC += \ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_AT32F435_437 \ + -DBOARD_TUD_RHPORT=0 LDFLAGS_GCC += \ -flto --specs=nosys.specs -nostdlib -nostartfiles @@ -21,24 +19,24 @@ SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ src/portable/synopsys/dwc2/hcd_dwc2.c \ src/portable/synopsys/dwc2/dwc2_common.c \ - $(AT32F435_437_SDK_SRC)/drivers/src/at32f435_437_gpio.c \ - $(AT32F435_437_SDK_SRC)/drivers/src/at32f435_437_misc.c \ - $(AT32F435_437_SDK_SRC)/drivers/src/at32f435_437_usart.c \ - $(AT32F435_437_SDK_SRC)/drivers/src/at32f435_437_crm.c \ - $(AT32F435_437_SDK_SRC)/drivers/src/at32f435_437_acc.c \ - $(AT32F435_437_SDK_SRC)/drivers/src/at32f435_437_exint.c \ - $(AT32F435_437_SDK_SRC)/cmsis/cm4/device_support/system_at32f435_437.c + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_crm.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_acc.c \ + $(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_exint.c \ + $(AT32_SDK_LIB)/cmsis/cm4/device_support/system_${AT32_FAMILY}.c INC += \ $(TOP)/$(BOARD_PATH) \ - $(TOP)/$(AT32F435_437_SDK_SRC)/drivers/inc \ - $(TOP)/$(AT32F435_437_SDK_SRC)/cmsis/cm4/core_support \ - $(TOP)/$(AT32F435_437_SDK_SRC)/cmsis/cm4/device_support \ + $(TOP)/$(AT32_SDK_LIB)/drivers/inc \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/core_support \ + $(TOP)/$(AT32_SDK_LIB)/cmsis/cm4/device_support -SRC_S += \ - $(FAMILY_PATH)/startup_at32f435_437.s +SRC_S_GCC += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/startup_${AT32_FAMILY}.s +SRC_S_IAR += ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/startup_${AT32_FAMILY}.s -# For freeRTOS port source -#FREERTOS_PORTABLE_SRC = $(FREERTOS_PORTABLE_PATH)/ARM_CM4F +LD_FILE_GCC ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/gcc/linker/${MCU_LINKER_NAME}_FLASH.ld +LD_FILE_IAR ?= ${AT32_SDK_LIB}/cmsis/cm4/device_support/startup/iar/linker/${MCU_LINKER_NAME}.icf flash: flash-atlink diff --git a/hw/bsp/at32f435_437/startup_at32f435_437.s b/hw/bsp/at32f435_437/startup_at32f435_437.s deleted file mode 100644 index 70bc4ec89..000000000 --- a/hw/bsp/at32f435_437/startup_at32f435_437.s +++ /dev/null @@ -1,569 +0,0 @@ -/** - ****************************************************************************** - * @file startup_at32f435_437.s - * @brief at32f435_437 devices vector table for gcc toolchain. - * this module performs: - * - set the initial sp - * - set the initial pc == reset_handler, - * - set the vector table entries with the exceptions isr address - * - configure the clock system and the external sram to - * be used as data memory (optional, to be enabled by user) - * - branches to main in the c library (which eventually - * calls main()). - * after reset the cortex-m4 processor is in thread mode, - * priority is privileged, and the stack is set to main. - ****************************************************************************** - */ - - .syntax unified - .cpu cortex-m4 - .fpu softvfp - .thumb - -.global g_pfnVectors -.global Default_Handler - -/* start address for the initialization values of the .data section. -defined in linker script */ -.word _sidata -/* start address for the .data section. defined in linker script */ -.word _sdata -/* end address for the .data section. defined in linker script */ -.word _edata -/* start address for the .bss section. defined in linker script */ -.word _sbss -/* end address for the .bss section. defined in linker script */ -.word _ebss -/* stack used for SystemInit_ExtMemCtl; always internal RAM used */ - -/** - * @brief This is the code that gets called when the processor first - * starts execution following a reset event. Only the absolutely - * necessary set is performed, after which the application - * supplied main() routine is called. - * @param None - * @retval None -*/ - - .section .text.Reset_Handler - .weak Reset_Handler - .type Reset_Handler, %function -Reset_Handler: - -/* Copy the data segment initializers from flash to SRAM */ - movs r1, #0 - b LoopCopyDataInit - -CopyDataInit: - ldr r3, =_sidata - ldr r3, [r3, r1] - str r3, [r0, r1] - adds r1, r1, #4 - -LoopCopyDataInit: - ldr r0, =_sdata - ldr r3, =_edata - adds r2, r0, r1 - cmp r2, r3 - bcc CopyDataInit - ldr r2, =_sbss - b LoopFillZerobss -/* Zero fill the bss segment. */ -FillZerobss: - movs r3, #0 - str r3, [r2], #4 - -LoopFillZerobss: - ldr r3, = _ebss - cmp r2, r3 - bcc FillZerobss - -/* Call the clock system initialization function.*/ - bl SystemInit -/* Call static constructors */ - bl __libc_init_array -/* Call the application's entry point.*/ - bl main - bx lr -.size Reset_Handler, .-Reset_Handler - -/** - * @brief This is the code that gets called when the processor receives an - * unexpected interrupt. This simply enters an infinite loop, preserving - * the system state for examination by a debugger. - * @param None - * @retval None -*/ - .section .text.Default_Handler,"ax",%progbits -Default_Handler: -Infinite_Loop: - b Infinite_Loop - .size Default_Handler, .-Default_Handler -/****************************************************************************** -* -* The minimal vector table for a Cortex M3. Note that the proper constructs -* must be placed on this to ensure that it ends up at physical address -* 0x0000.0000. -* -*******************************************************************************/ - .section .isr_vector,"a",%progbits - .type g_pfnVectors, %object - .size g_pfnVectors, .-g_pfnVectors - - -g_pfnVectors: - .word _estack - .word Reset_Handler - .word NMI_Handler - .word HardFault_Handler - .word MemManage_Handler - .word BusFault_Handler - .word UsageFault_Handler - .word 0 - .word 0 - .word 0 - .word 0 - .word SVC_Handler - .word DebugMon_Handler - .word 0 - .word PendSV_Handler - .word SysTick_Handler - - /* External Interrupts */ - .word WWDT_IRQHandler /* Window Watchdog Timer */ - .word PVM_IRQHandler /* PVM through EXINT Line detect */ - .word TAMP_STAMP_IRQHandler /* Tamper and TimeStamps through the EXINT line */ - .word ERTC_WKUP_IRQHandler /* ERTC Wakeup through the EXINT line */ - .word FLASH_IRQHandler /* Flash */ - .word CRM_IRQHandler /* CRM */ - .word EXINT0_IRQHandler /* EXINT Line 0 */ - .word EXINT1_IRQHandler /* EXINT Line 1 */ - .word EXINT2_IRQHandler /* EXINT Line 2 */ - .word EXINT3_IRQHandler /* EXINT Line 3 */ - .word EXINT4_IRQHandler /* EXINT Line 4 */ - .word EDMA_Stream1_IRQHandler /* EDMA Stream 1 */ - .word EDMA_Stream2_IRQHandler /* EDMA Stream 2 */ - .word EDMA_Stream3_IRQHandler /* EDMA Stream 3 */ - .word EDMA_Stream4_IRQHandler /* EDMA Stream 4 */ - .word EDMA_Stream5_IRQHandler /* EDMA Stream 5 */ - .word EDMA_Stream6_IRQHandler /* EDMA Stream 6 */ - .word EDMA_Stream7_IRQHandler /* EDMA Stream 7 */ - .word ADC1_2_3_IRQHandler /* ADC1 & ADC2 & ADC3 */ - .word CAN1_TX_IRQHandler /* CAN1 TX */ - .word CAN1_RX0_IRQHandler /* CAN1 RX0 */ - .word CAN1_RX1_IRQHandler /* CAN1 RX1 */ - .word CAN1_SE_IRQHandler /* CAN1 SE */ - .word EXINT9_5_IRQHandler /* EXINT Line [9:5] */ - .word TMR1_BRK_TMR9_IRQHandler /* TMR1 Brake and TMR9 */ - .word TMR1_OVF_TMR10_IRQHandler /* TMR1 Overflow and TMR10 */ - .word TMR1_TRG_HALL_TMR11_IRQHandler /* TMR1 Trigger and hall and TMR11 */ - .word TMR1_CH_IRQHandler /* TMR1 Channel */ - .word TMR2_GLOBAL_IRQHandler /* TMR2 */ - .word TMR3_GLOBAL_IRQHandler /* TMR3 */ - .word TMR4_GLOBAL_IRQHandler /* TMR4 */ - .word I2C1_EVT_IRQHandler /* I2C1 Event */ - .word I2C1_ERR_IRQHandler /* I2C1 Error */ - .word I2C2_EVT_IRQHandler /* I2C2 Event */ - .word I2C2_ERR_IRQHandler /* I2C2 Error */ - .word SPI1_IRQHandler /* SPI1 */ - .word SPI2_I2S2EXT_IRQHandler /* SPI2 */ - .word USART1_IRQHandler /* USART1 */ - .word USART2_IRQHandler /* USART2 */ - .word USART3_IRQHandler /* USART3 */ - .word EXINT15_10_IRQHandler /* EXINT Line [15:10] */ - .word ERTCAlarm_IRQHandler /* RTC Alarm through EXINT Line */ - .word OTGFS1_WKUP_IRQHandler /* OTGFS1 Wakeup from suspend */ - .word TMR8_BRK_TMR12_IRQHandler /* TMR8 Brake and TMR12 */ - .word TMR8_OVF_TMR13_IRQHandler /* TMR8 Overflow and TMR13 */ - .word TMR8_TRG_HALL_TMR14_IRQHandler /* TMR8 Trigger and hall and TMR14 */ - .word TMR8_CH_IRQHandler /* TMR8 Channel */ - .word EDMA_Stream8_IRQHandler /* EDMA Stream 8 */ - .word XMC_IRQHandler /* XMC */ - .word SDIO1_IRQHandler /* SDIO1 */ - .word TMR5_GLOBAL_IRQHandler /* TMR5 */ - .word SPI3_I2S3EXT_IRQHandler /* SPI3 */ - .word UART4_IRQHandler /* UART4 */ - .word UART5_IRQHandler /* UART5 */ - .word TMR6_DAC_GLOBAL_IRQHandler /* TMR6 & DAC */ - .word TMR7_GLOBAL_IRQHandler /* TMR7 */ - .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ - .word DMA1_Channel2_IRQHandler /* DMA1 Channel 2 */ - .word DMA1_Channel3_IRQHandler /* DMA1 Channel 3 */ - .word DMA1_Channel4_IRQHandler /* DMA1 Channel 4 */ - .word DMA1_Channel5_IRQHandler /* DMA1 Channel 5 */ - .word EMAC_IRQHandler /* EMAC */ - .word EMAC_WKUP_IRQHandler /* EMAC Wakeup */ - .word CAN2_TX_IRQHandler /* CAN2 TX */ - .word CAN2_RX0_IRQHandler /* CAN2 RX0 */ - .word CAN2_RX1_IRQHandler /* CAN2 RX1 */ - .word CAN2_SE_IRQHandler /* CAN2 SE */ - .word OTGFS1_IRQHandler /* OTGFS1 */ - .word DMA1_Channel6_IRQHandler /* DMA1 Channel 6 */ - .word DMA1_Channel7_IRQHandler /* DMA1 Channel 7 */ - .word 0 /* Reserved */ - .word USART6_IRQHandler /* USART6 */ - .word I2C3_EVT_IRQHandler /* I2C3 Event */ - .word I2C3_ERR_IRQHandler /* I2C3 Error */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word OTGFS2_WKUP_IRQHandler /* OTGFS2 Wakeup from suspend */ - .word OTGFS2_IRQHandler /* OTGFS2 */ - .word DVP_IRQHandler /* DVP */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word FPU_IRQHandler /* FPU */ - .word UART7_IRQHandler /* UART7 */ - .word UART8_IRQHandler /* UART8 */ - .word SPI4_IRQHandler /* SPI4 */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word QSPI2_IRQHandler /* QSPI2 */ - .word QSPI1_IRQHandler /* QSPI1 */ - .word 0 /* Reserved */ - .word DMAMUX_IRQHandler /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word 0 /* Reserved */ - .word SDIO2_IRQHandler /* SDIO2 */ - .word ACC_IRQHandler /* ACC */ - .word TMR20_BRK_IRQHandler /* TMR20 Brake */ - .word TMR20_OVF_IRQHandler /* TMR20 Overflow */ - .word TMR20_TRG_HALL_IRQHandler /* TMR20 Trigger and hall */ - .word TMR20_CH_IRQHandler /* TMR20 Channel */ - .word DMA2_Channel1_IRQHandler /* DMA2 Channel 1 */ - .word DMA2_Channel2_IRQHandler /* DMA2 Channel 2 */ - .word DMA2_Channel3_IRQHandler /* DMA2 Channel 3 */ - .word DMA2_Channel4_IRQHandler /* DMA2 Channel 4 */ - .word DMA2_Channel5_IRQHandler /* DMA2 Channel 5 */ - .word DMA2_Channel6_IRQHandler /* DMA2 Channel 6 */ - .word DMA2_Channel7_IRQHandler /* DMA2 Channel 7 */ - -/******************************************************************************* -* -* Provide weak aliases for each Exception handler to the Default_Handler. -* As they are weak aliases, any function with the same name will override -* this definition. -* -*******************************************************************************/ - .weak NMI_Handler - .thumb_set NMI_Handler,Default_Handler - - .weak HardFault_Handler - .thumb_set HardFault_Handler,Default_Handler - - .weak MemManage_Handler - .thumb_set MemManage_Handler,Default_Handler - - .weak BusFault_Handler - .thumb_set BusFault_Handler,Default_Handler - - .weak UsageFault_Handler - .thumb_set UsageFault_Handler,Default_Handler - - .weak SVC_Handler - .thumb_set SVC_Handler,Default_Handler - - .weak DebugMon_Handler - .thumb_set DebugMon_Handler,Default_Handler - - .weak PendSV_Handler - .thumb_set PendSV_Handler,Default_Handler - - .weak SysTick_Handler - .thumb_set SysTick_Handler,Default_Handler - - .weak WWDT_IRQHandler - .thumb_set WWDT_IRQHandler,Default_Handler - - .weak PVM_IRQHandler - .thumb_set PVM_IRQHandler,Default_Handler - - .weak TAMP_STAMP_IRQHandler - .thumb_set TAMP_STAMP_IRQHandler,Default_Handler - - .weak ERTC_WKUP_IRQHandler - .thumb_set ERTC_WKUP_IRQHandler,Default_Handler - - .weak FLASH_IRQHandler - .thumb_set FLASH_IRQHandler,Default_Handler - - .weak CRM_IRQHandler - .thumb_set CRM_IRQHandler,Default_Handler - - .weak EXINT0_IRQHandler - .thumb_set EXINT0_IRQHandler,Default_Handler - - .weak EXINT1_IRQHandler - .thumb_set EXINT1_IRQHandler,Default_Handler - - .weak EXINT2_IRQHandler - .thumb_set EXINT2_IRQHandler,Default_Handler - - .weak EXINT3_IRQHandler - .thumb_set EXINT3_IRQHandler,Default_Handler - - .weak EXINT4_IRQHandler - .thumb_set EXINT4_IRQHandler,Default_Handler - - .weak EDMA_Stream1_IRQHandler - .thumb_set EDMA_Stream1_IRQHandler,Default_Handler - - .weak EDMA_Stream2_IRQHandler - .thumb_set EDMA_Stream2_IRQHandler,Default_Handler - - .weak EDMA_Stream3_IRQHandler - .thumb_set EDMA_Stream3_IRQHandler,Default_Handler - - .weak EDMA_Stream4_IRQHandler - .thumb_set EDMA_Stream4_IRQHandler,Default_Handler - - .weak EDMA_Stream5_IRQHandler - .thumb_set EDMA_Stream5_IRQHandler,Default_Handler - - .weak EDMA_Stream6_IRQHandler - .thumb_set EDMA_Stream6_IRQHandler,Default_Handler - - .weak EDMA_Stream7_IRQHandler - .thumb_set EDMA_Stream7_IRQHandler,Default_Handler - - .weak ADC1_2_3_IRQHandler - .thumb_set ADC1_2_3_IRQHandler,Default_Handler - - .weak CAN1_TX_IRQHandler - .thumb_set CAN1_TX_IRQHandler,Default_Handler - - .weak CAN1_RX0_IRQHandler - .thumb_set CAN1_RX0_IRQHandler,Default_Handler - - .weak CAN1_RX1_IRQHandler - .thumb_set CAN1_RX1_IRQHandler,Default_Handler - - .weak CAN1_SE_IRQHandler - .thumb_set CAN1_SE_IRQHandler,Default_Handler - - .weak EXINT9_5_IRQHandler - .thumb_set EXINT9_5_IRQHandler,Default_Handler - - .weak TMR1_BRK_TMR9_IRQHandler - .thumb_set TMR1_BRK_TMR9_IRQHandler,Default_Handler - - .weak TMR1_OVF_TMR10_IRQHandler - .thumb_set TMR1_OVF_TMR10_IRQHandler,Default_Handler - - .weak TMR1_TRG_HALL_TMR11_IRQHandler - .thumb_set TMR1_TRG_HALL_TMR11_IRQHandler,Default_Handler - - .weak TMR1_CH_IRQHandler - .thumb_set TMR1_CH_IRQHandler,Default_Handler - - .weak TMR2_GLOBAL_IRQHandler - .thumb_set TMR2_GLOBAL_IRQHandler,Default_Handler - - .weak TMR3_GLOBAL_IRQHandler - .thumb_set TMR3_GLOBAL_IRQHandler,Default_Handler - - .weak TMR4_GLOBAL_IRQHandler - .thumb_set TMR4_GLOBAL_IRQHandler,Default_Handler - - .weak I2C1_EVT_IRQHandler - .thumb_set I2C1_EVT_IRQHandler,Default_Handler - - .weak I2C1_ERR_IRQHandler - .thumb_set I2C1_ERR_IRQHandler,Default_Handler - - .weak I2C2_EVT_IRQHandler - .thumb_set I2C2_EVT_IRQHandler,Default_Handler - - .weak I2C2_ERR_IRQHandler - .thumb_set I2C2_ERR_IRQHandler,Default_Handler - - .weak SPI1_IRQHandler - .thumb_set SPI1_IRQHandler,Default_Handler - - .weak SPI2_I2S2EXT_IRQHandler - .thumb_set SPI2_I2S2EXT_IRQHandler,Default_Handler - - .weak USART1_IRQHandler - .thumb_set USART1_IRQHandler,Default_Handler - - .weak USART2_IRQHandler - .thumb_set USART2_IRQHandler,Default_Handler - - .weak USART3_IRQHandler - .thumb_set USART3_IRQHandler,Default_Handler - - .weak EXINT15_10_IRQHandler - .thumb_set EXINT15_10_IRQHandler,Default_Handler - - .weak ERTCAlarm_IRQHandler - .thumb_set ERTCAlarm_IRQHandler,Default_Handler - - .weak OTGFS1_WKUP_IRQHandler - .thumb_set OTGFS1_WKUP_IRQHandler,Default_Handler - - .weak TMR8_BRK_TMR12_IRQHandler - .thumb_set TMR8_BRK_TMR12_IRQHandler,Default_Handler - - .weak TMR8_OVF_TMR13_IRQHandler - .thumb_set TMR8_OVF_TMR13_IRQHandler,Default_Handler - - .weak TMR8_TRG_HALL_TMR14_IRQHandler - .thumb_set TMR8_TRG_HALL_TMR14_IRQHandler,Default_Handler - - .weak TMR8_CH_IRQHandler - .thumb_set TMR8_CH_IRQHandler,Default_Handler - - .weak EDMA_Stream8_IRQHandler - .thumb_set EDMA_Stream8_IRQHandler,Default_Handler - - .weak XMC_IRQHandler - .thumb_set XMC_IRQHandler,Default_Handler - - .weak SDIO1_IRQHandler - .thumb_set SDIO1_IRQHandler,Default_Handler - - .weak TMR5_GLOBAL_IRQHandler - .thumb_set TMR5_GLOBAL_IRQHandler,Default_Handler - - .weak SPI3_I2S3EXT_IRQHandler - .thumb_set SPI3_I2S3EXT_IRQHandler,Default_Handler - - .weak UART4_IRQHandler - .thumb_set UART4_IRQHandler,Default_Handler - - .weak UART5_IRQHandler - .thumb_set UART5_IRQHandler,Default_Handler - - .weak TMR6_DAC_GLOBAL_IRQHandler - .thumb_set TMR6_DAC_GLOBAL_IRQHandler,Default_Handler - - .weak TMR7_GLOBAL_IRQHandler - .thumb_set TMR7_GLOBAL_IRQHandler,Default_Handler - - .weak DMA1_Channel1_IRQHandler - .thumb_set DMA1_Channel1_IRQHandler,Default_Handler - - .weak DMA1_Channel2_IRQHandler - .thumb_set DMA1_Channel2_IRQHandler,Default_Handler - - .weak DMA1_Channel3_IRQHandler - .thumb_set DMA1_Channel3_IRQHandler,Default_Handler - - .weak DMA1_Channel4_IRQHandler - .thumb_set DMA1_Channel4_IRQHandler,Default_Handler - - .weak DMA1_Channel5_IRQHandler - .thumb_set DMA1_Channel5_IRQHandler,Default_Handler - - .weak EMAC_IRQHandler - .thumb_set EMAC_IRQHandler,Default_Handler - - .weak EMAC_WKUP_IRQHandler - .thumb_set EMAC_WKUP_IRQHandler,Default_Handler - - .weak CAN2_TX_IRQHandler - .thumb_set CAN2_TX_IRQHandler,Default_Handler - - .weak CAN2_RX0_IRQHandler - .thumb_set CAN2_RX0_IRQHandler ,Default_Handler - - .weak CAN2_RX1_IRQHandler - .thumb_set CAN2_RX1_IRQHandler ,Default_Handler - - .weak CAN2_SE_IRQHandler - .thumb_set CAN2_SE_IRQHandler,Default_Handler - - .weak OTGFS1_IRQHandler - .thumb_set OTGFS1_IRQHandler,Default_Handler - - .weak DMA1_Channel6_IRQHandler - .thumb_set DMA1_Channel6_IRQHandler,Default_Handler - - .weak DMA1_Channel7_IRQHandler - .thumb_set DMA1_Channel7_IRQHandler,Default_Handler - - .weak USART6_IRQHandler - .thumb_set USART6_IRQHandler,Default_Handler - - .weak I2C3_EVT_IRQHandler - .thumb_set I2C3_EVT_IRQHandler,Default_Handler - - .weak I2C3_ERR_IRQHandler - .thumb_set I2C3_ERR_IRQHandler,Default_Handler - - .weak OTGFS2_WKUP_IRQHandler - .thumb_set OTGFS2_WKUP_IRQHandler,Default_Handler - - .weak OTGFS2_IRQHandler - .thumb_set OTGFS2_IRQHandler,Default_Handler - - .weak DVP_IRQHandler - .thumb_set DVP_IRQHandler,Default_Handler - - .weak FPU_IRQHandler - .thumb_set FPU_IRQHandler,Default_Handler - - .weak UART7_IRQHandler - .thumb_set UART7_IRQHandler,Default_Handler - - .weak UART8_IRQHandler - .thumb_set UART8_IRQHandler,Default_Handler - - .weak SPI4_IRQHandler - .thumb_set SPI4_IRQHandler,Default_Handler - - .weak QSPI2_IRQHandler - .thumb_set QSPI2_IRQHandler,Default_Handler - - .weak QSPI1_IRQHandler - .thumb_set QSPI1_IRQHandler,Default_Handler - - .weak DMAMUX_IRQHandler - .thumb_set DMAMUX_IRQHandler ,Default_Handler - - .weak SDIO2_IRQHandler - .thumb_set SDIO2_IRQHandler ,Default_Handler - - .weak ACC_IRQHandler - .thumb_set ACC_IRQHandler,Default_Handler - - .weak TMR20_BRK_IRQHandler - .thumb_set TMR20_BRK_IRQHandler,Default_Handler - - .weak TMR20_OVF_IRQHandler - .thumb_set TMR20_OVF_IRQHandler,Default_Handler - - .weak TMR20_TRG_HALL_IRQHandler - .thumb_set TMR20_TRG_HALL_IRQHandler,Default_Handler - - .weak TMR20_CH_IRQHandler - .thumb_set TMR20_CH_IRQHandler,Default_Handler - - .weak DMA2_Channel1_IRQHandler - .thumb_set DMA2_Channel1_IRQHandler,Default_Handler - - .weak DMA2_Channel2_IRQHandler - .thumb_set DMA2_Channel2_IRQHandler,Default_Handler - - .weak DMA2_Channel3_IRQHandler - .thumb_set DMA2_Channel3_IRQHandler,Default_Handler - - .weak DMA2_Channel4_IRQHandler - .thumb_set DMA2_Channel4_IRQHandler,Default_Handler - - .weak DMA2_Channel5_IRQHandler - .thumb_set DMA2_Channel5_IRQHandler,Default_Handler - - .weak DMA2_Channel6_IRQHandler - .thumb_set DMA2_Channel6_IRQHandler,Default_Handler - - .weak DMA2_Channel7_IRQHandler - .thumb_set DMA2_Channel7_IRQHandler,Default_Handler From e0f2343954c71743358f2b2362bef64bbc68e4a3 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 31 Jul 2025 23:26:27 +0700 Subject: [PATCH 318/382] clean up --- src/portable/st/stm32_fsdev/fsdev_at32.h | 148 +++++++++++------------ src/portable/synopsys/dwc2/dwc2_at32.h | 92 ++++++-------- src/portable/synopsys/dwc2/dwc2_common.c | 16 +-- 3 files changed, 117 insertions(+), 139 deletions(-) diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h index 5f2ce4ba2..3a785bbbd 100644 --- a/src/portable/st/stm32_fsdev/fsdev_at32.h +++ b/src/portable/st/stm32_fsdev/fsdev_at32.h @@ -35,82 +35,6 @@ #endif -//#include "fsdev_common.h" - -//--------------------------------------------------------------------+ -// -//--------------------------------------------------------------------+ - -#if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) -static const IRQn_Type fsdev_irq[] = { - USBFS_H_CAN1_TX_IRQn, - USBFS_L_CAN1_RX0_IRQn, - USBFSWakeUp_IRQn -}; -enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; - -#else - #error "Unsupported MCU" -#endif - -void dcd_int_enable(uint8_t rhport) { - (void)rhport; - #if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) - // AT32F403A/407 devices allow to remap the USB interrupt vectors from - // shared USB/CAN IRQs to separate CAN and USB IRQs. - // This dynamically checks if this remap is active to enable the right IRQs. - if (CRM->intmap_bit.usbintmap) { - NVIC_DisableIRQ(USBFS_MAPH_IRQn); - NVIC_DisableIRQ(USBFS_MAPL_IRQn); - NVIC_DisableIRQ(USBFSWakeUp_IRQn); - } else - #endif - { - for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { - NVIC_EnableIRQ(fsdev_irq[i]); - } - } -} - -void dcd_int_disable(uint8_t rhport) { - (void)rhport; - #if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) - // AT32F403A/407 devices allow to remap the USB interrupt vectors from - // shared USB/CAN IRQs to separate CAN and USB IRQs. - // This dynamically checks if this remap is active to enable the right IRQs. - if (CRM->intmap_bit.usbintmap) { - NVIC_DisableIRQ(USBFS_MAPH_IRQn); - NVIC_DisableIRQ(USBFS_MAPL_IRQn); - NVIC_DisableIRQ(USBFSWakeUp_IRQn); - } else - #endif - { - for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { - NVIC_DisableIRQ(fsdev_irq[i]); - } - } -} - -void dcd_disconnect(uint8_t rhport) { - (void) rhport; - /* disable usb phy */ - //USB->ctrl_bit.disusb = TRUE; - *(int *)(0x40000000+0x5C00+0x40) |= (1<<1); - *(int *)(0x40000000+0x5C00+0x60) |= (1<<1); - /* D+ 1.5k pull-up disable */ - //USB->cfg_bit.puo = TRUE; -} - -void dcd_connect(uint8_t rhport) { - (void) rhport; - /* enable usb phy */ - //USB->ctrl_bit.disusb = 0; - *(int *)(0x40000000+0x5C00+0x40) &= ~(1<<1); - *(int *)(0x40000000+0x5C00+0x60) &= ~(1<<1); - /* Dp 1.5k pull-up enable */ - //USB->cfg_bit.puo = 0; -} - #define FSDEV_PMA_SIZE (512u) #define FSDEV_REG_BASE (APB1PERIPH_BASE + 0x00005C00UL) #define FSDEV_PMA_BASE (APB1PERIPH_BASE + 0x00006000UL) @@ -221,4 +145,76 @@ void dcd_connect(uint8_t rhport) { #define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */ #define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK) +#include "fsdev_type.h" + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +#if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) +static const IRQn_Type fsdev_irq[] = { + USBFS_H_CAN1_TX_IRQn, + USBFS_L_CAN1_RX0_IRQn, + USBFSWakeUp_IRQn +}; +enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) }; + +#else + #error "Unsupported MCU" +#endif + +void dcd_int_enable(uint8_t rhport) { + (void)rhport; + #if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) + // AT32F403A/407 devices allow to remap the USB interrupt vectors from + // shared USB/CAN IRQs to separate CAN and USB IRQs. + // This dynamically checks if this remap is active to enable the right IRQs. + if (CRM->intmap_bit.usbintmap) { + NVIC_DisableIRQ(USBFS_MAPH_IRQn); + NVIC_DisableIRQ(USBFS_MAPL_IRQn); + NVIC_DisableIRQ(USBFSWakeUp_IRQn); + } else + #endif + { + for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { + NVIC_EnableIRQ(fsdev_irq[i]); + } + } +} + +void dcd_int_disable(uint8_t rhport) { + (void)rhport; + #if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413) + // AT32F403A/407 devices allow to remap the USB interrupt vectors from + // shared USB/CAN IRQs to separate CAN and USB IRQs. + // This dynamically checks if this remap is active to enable the right IRQs. + if (CRM->intmap_bit.usbintmap) { + NVIC_DisableIRQ(USBFS_MAPH_IRQn); + NVIC_DisableIRQ(USBFS_MAPL_IRQn); + NVIC_DisableIRQ(USBFSWakeUp_IRQn); + } else + #endif + { + for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) { + NVIC_DisableIRQ(fsdev_irq[i]); + } + } +} + +void dcd_disconnect(uint8_t rhport) { + (void) rhport; + /* disable usb phy */ + FSDEV_REG->CNTR |= USB_CNTR_PDWN; + /* D+ 1.5k pull-up disable, USB->cfg_bit.puo = TRUE; */ + *(uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1); +} + +void dcd_connect(uint8_t rhport) { + (void) rhport; + /* enable usb phy */ + FSDEV_REG->CNTR &= ~USB_CNTR_PDWN; + /* Dp 1.5k pull-up enable, USB->cfg_bit.puo = 0; */ + *(uint32_t *)(FSDEV_REG_BASE+0x60) &= ~(1u<<1); +} + #endif diff --git a/src/portable/synopsys/dwc2/dwc2_at32.h b/src/portable/synopsys/dwc2/dwc2_at32.h index 1150d825b..37b6592c4 100644 --- a/src/portable/synopsys/dwc2/dwc2_at32.h +++ b/src/portable/synopsys/dwc2/dwc2_at32.h @@ -67,66 +67,52 @@ extern "C" { #endif -static const dwc2_controller_t _dwc2_controller[] = -{ - { .reg_base = DWC2_OTG1_REG_BASE, .irqnum = OTG1_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = OTG1_FIFO_SIZE }, - #if defined DWC2_OTG2_REG_BASE - { .reg_base = DWC2_OTG2_REG_BASE, .irqnum = OTG2_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = OTG2_FIFO_SIZE } - #endif -}; + static const dwc2_controller_t _dwc2_controller[] = { +{.reg_base = DWC2_OTG1_REG_BASE, .irqnum = OTG1_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = OTG1_FIFO_SIZE}, +#if defined DWC2_OTG2_REG_BASE + {.reg_base = DWC2_OTG2_REG_BASE, .irqnum = OTG2_IRQn, .ep_count = DWC2_EP_MAX, .ep_fifo_size = OTG2_FIFO_SIZE} +#endif + }; -TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { - (void) role; - const IRQn_Type irqn = (IRQn_Type) _dwc2_controller[rhport].irqnum; - if (enabled) { - NVIC_EnableIRQ(irqn); - } else { - NVIC_DisableIRQ(irqn); - } -} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_int_set(uint8_t rhport, tusb_role_t role, bool enabled) { + (void) role; + const IRQn_Type irqn = (IRQn_Type) _dwc2_controller[rhport].irqnum; + if (enabled) { + NVIC_EnableIRQ(irqn); + } else { + NVIC_DisableIRQ(irqn); + } + } -TU_ATTR_ALWAYS_INLINE -static inline void dwc2_dcd_int_enable(uint8_t rhport) -{ - NVIC_EnableIRQ(_dwc2_controller[rhport].irqnum); -} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_enable(uint8_t rhport) { NVIC_EnableIRQ(_dwc2_controller[rhport].irqnum); + } -TU_ATTR_ALWAYS_INLINE -static inline void dwc2_dcd_int_disable (uint8_t rhport) -{ - NVIC_DisableIRQ(_dwc2_controller[rhport].irqnum); -} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_dcd_int_disable(uint8_t rhport) { + NVIC_DisableIRQ(_dwc2_controller[rhport].irqnum); + } -static inline void dwc2_remote_wakeup_delay(void) -{ - // try to delay for 1 ms - uint32_t count = system_core_clock / 1000; - while ( count-- ) __asm volatile ("nop"); -} + TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { + // try to delay for 1 ms + uint32_t count = system_core_clock / 1000; + while (count--) __asm volatile("nop"); + } -// MCU specific PHY init, called BEFORE core reset -static inline void dwc2_phy_init(dwc2_regs_t * dwc2, uint8_t hs_phy_type) -{ - (void) dwc2; - // Enable on-chip HS PHY - if (hs_phy_type == GHWCFG2_HSPHY_UTMI || hs_phy_type == GHWCFG2_HSPHY_UTMI_ULPI) - { + // MCU specific PHY init, called BEFORE core reset + TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_init(dwc2_regs_t *dwc2, uint8_t hs_phy_type) { + (void) dwc2; + // Enable on-chip HS PHY + if (hs_phy_type == GHWCFG2_HSPHY_UTMI || hs_phy_type == GHWCFG2_HSPHY_UTMI_ULPI) { + } else if (hs_phy_type == GHWCFG2_HSPHY_NOT_SUPPORTED) { + } + } - } - else if(hs_phy_type == GHWCFG2_HSPHY_NOT_SUPPORTED) - { + // MCU specific PHY update, it is called AFTER init() and core reset + TU_ATTR_ALWAYS_INLINE static inline void dwc2_phy_update(dwc2_regs_t *dwc2, uint8_t hs_phy_type) { + (void) dwc2; + (void) hs_phy_type; - } -} - -// MCU specific PHY update, it is called AFTER init() and core reset -static inline void dwc2_phy_update(dwc2_regs_t * dwc2, uint8_t hs_phy_type) -{ - (void) dwc2; - (void) hs_phy_type; - - dwc2->stm32_gccfg |= STM32_GCCFG_PWRDWN | STM32_GCCFG_DCDEN | STM32_GCCFG_PDEN; -} + dwc2->stm32_gccfg |= STM32_GCCFG_PWRDWN | STM32_GCCFG_DCDEN | STM32_GCCFG_PDEN; + } #ifdef __cplusplus } diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 56326d5a7..b001f343d 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -120,13 +120,9 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { // Set 16-bit interface if supported if (ghwcfg4.phy_data_width) { + #if CFG_TUSB_MCU != OPT_MCU_AT32F402_405 // at32f402_405 does not actually support 16-bit gusbcfg |= GUSBCFG_PHYIF16; // 16 bit - - /* at32f402_405 does not actually support 16-bit */ - #if CFG_TUSB_MCU == OPT_MCU_AT32F402_405 - gusbcfg &= ~GUSBCFG_PHYIF16; // 8 bit #endif - } else { gusbcfg &= ~GUSBCFG_PHYIF16; // 8 bit } @@ -145,12 +141,12 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { // - 9 if using 8-bit PHY interface // - 5 if using 16-bit PHY interface gusbcfg &= ~GUSBCFG_TRDT_Msk; - gusbcfg |= (dwc2->ghwcfg4_bm.phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos; - /* at32f402_405 does not actually support 16-bit */ - #if CFG_TUSB_MCU == OPT_MCU_AT32F402_405 - gusbcfg |= (dwc2->ghwcfg4_bm.phy_data_width ? 9u : 9u) << GUSBCFG_TRDT_Pos; - #endif +#if CFG_TUSB_MCU == OPT_MCU_AT32F402_405 // at32f402_405 does not actually support 16-bit + gusbcfg |= 9u << GUSBCFG_TRDT_Pos; +#else + gusbcfg |= (dwc2->ghwcfg4_bm.phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos; +#endif dwc2->gusbcfg = gusbcfg; From 9290788a2376277740742cc07873143a034193cf Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 1 Aug 2025 11:26:04 +0700 Subject: [PATCH 319/382] add at32 to README.rst, rename at32 board to lower case, correct name to match mcu, add meta data --- .circleci/config.yml | 2 +- .idea/cmake.xml | 3 +++ README.rst | 6 ++++++ docs/reference/boards.rst | 17 ++++++++++++++++- docs/reference/dependencies.rst | 10 +++++++++- examples/device/net_lwip_webserver/skip.txt | 2 +- .../board.cmake | 0 .../board.h | 5 +++++ .../board.mk | 0 hw/bsp/at32f402_405/family.c | 4 ++++ .../board.cmake | 0 .../board.h | 10 ++++++++++ .../board.mk | 0 hw/bsp/at32f403a_407/family.c | 4 ++++ .../board.cmake | 0 .../{AT_START_F413 => at_start_f413}/board.h | 5 +++++ .../{AT_START_F413 => at_start_f413}/board.mk | 0 hw/bsp/at32f413/family.c | 4 ++++ .../board.cmake | 0 .../{AT_START_F415 => at_start_f415}/board.h | 5 +++++ .../{AT_START_F415 => at_start_f415}/board.mk | 0 hw/bsp/at32f415/family.c | 4 ++++ .../board.cmake | 0 .../{AT_START_F423 => at_start_f423}/board.h | 5 +++++ .../{AT_START_F423 => at_start_f423}/board.mk | 0 hw/bsp/at32f423/family.c | 4 ++++ .../board.cmake | 0 .../{AT_START_F425 => at_start_f425}/board.h | 5 +++++ .../{AT_START_F425 => at_start_f425}/board.mk | 0 hw/bsp/at32f425/family.c | 4 ++++ .../board.cmake | 0 .../board.h | 5 +++++ .../board.mk | 0 hw/bsp/at32f435_437/family.c | 4 ++++ 34 files changed, 104 insertions(+), 4 deletions(-) rename hw/bsp/at32f402_405/boards/{AT_START_F402_405 => at_start_f405}/board.cmake (100%) rename hw/bsp/at32f402_405/boards/{AT_START_F402_405 => at_start_f405}/board.h (98%) rename hw/bsp/at32f402_405/boards/{AT_START_F402_405 => at_start_f405}/board.mk (100%) rename hw/bsp/at32f403a_407/boards/{AT_START_F403A_407 => at_start_f403a}/board.cmake (100%) rename hw/bsp/at32f403a_407/boards/{AT_START_F403A_407 => at_start_f403a}/board.h (86%) rename hw/bsp/at32f403a_407/boards/{AT_START_F403A_407 => at_start_f403a}/board.mk (100%) rename hw/bsp/at32f413/boards/{AT_START_F413 => at_start_f413}/board.cmake (100%) rename hw/bsp/at32f413/boards/{AT_START_F413 => at_start_f413}/board.h (95%) rename hw/bsp/at32f413/boards/{AT_START_F413 => at_start_f413}/board.mk (100%) rename hw/bsp/at32f415/boards/{AT_START_F415 => at_start_f415}/board.cmake (100%) rename hw/bsp/at32f415/boards/{AT_START_F415 => at_start_f415}/board.h (96%) rename hw/bsp/at32f415/boards/{AT_START_F415 => at_start_f415}/board.mk (100%) rename hw/bsp/at32f423/boards/{AT_START_F423 => at_start_f423}/board.cmake (100%) rename hw/bsp/at32f423/boards/{AT_START_F423 => at_start_f423}/board.h (97%) rename hw/bsp/at32f423/boards/{AT_START_F423 => at_start_f423}/board.mk (100%) rename hw/bsp/at32f425/boards/{AT_START_F425 => at_start_f425}/board.cmake (100%) rename hw/bsp/at32f425/boards/{AT_START_F425 => at_start_f425}/board.h (97%) rename hw/bsp/at32f425/boards/{AT_START_F425 => at_start_f425}/board.mk (100%) rename hw/bsp/at32f435_437/boards/{AT_START_F435_437 => at_start_f437}/board.cmake (100%) rename hw/bsp/at32f435_437/boards/{AT_START_F435_437 => at_start_f437}/board.h (98%) rename hw/bsp/at32f435_437/boards/{AT_START_F435_437 => at_start_f437}/board.mk (100%) diff --git a/.circleci/config.yml b/.circleci/config.yml index c2f6c4356..3342cbc65 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -32,7 +32,7 @@ jobs: BUILDSYSTEM_TOOLCHAIN+=("cmake arm-iar") fi - RESOURCE_LARGE='["nrf", "imxrt", "stm32f4", "stm32h7"]' + RESOURCE_LARGE='["nrf", "imxrt", "stm32f4", "stm32h7 stm32h7rs"]' gen_build_entry() { local build_system="$1" diff --git a/.idea/cmake.xml b/.idea/cmake.xml index 7e0a9be92..f5e5d1f0e 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -163,12 +163,15 @@ + + + \ No newline at end of file diff --git a/README.rst b/README.rst index 2a756a97f..d6830e707 100644 --- a/README.rst +++ b/README.rst @@ -109,6 +109,12 @@ Supported CPUs | | MAX32 650, 666, 690, | ✔ | | ✔ | musb | 1-dir ep | | | MAX78002 | | | | | | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ +| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | | +| +-----------------------------+--------+------+-----------+------------------------+-------------------+ +| | F415, F435_437, F423, F425 | ✔ | ✔ | | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+-------------------+ +| | F402_F405 | ✔ | ✔ | ✔ | dwc2 | F405 is HS | ++--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ | Brigetek | FT90x | ✔ | | ✔ | ft9xx | 1-dir ep | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ | Broadcom | BCM2711, BCM2837 | ✔ | | ✔ | dwc2 | | diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 824b1214b..289ec543a 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -27,6 +27,21 @@ max32690evkit MAX32690 EVKIT maxim https://www.analog.com/en/resources/e max78002evkit MAX78002 EVKIT maxim https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/max78002evkit.html ============= ================ ======== ================================================================================================================= ====== +Artery +----- + +============== ============== ============= ================================================== ====== +Board Name Family URL Note +============== ============== ============= ================================================== ====== +at_start_f405 AT-START-F405 at32f402_405 https://www.arterychip.com/en/product/AT32F405.jsp +at_start_f403a AT-START-F403a at32f403a_407 https://www.arterychip.com/en/product/AT32F403.jsp +at_start_f413 AT-START-F413 at32f413 https://www.arterychip.com/en/product/AT32F413.jsp +at_start_f415 AT-START-F415 at32f415 https://www.arterychip.com/en/product/AT32F415.jsp +at_start_f423 AT-START-F423 at32f423 https://www.arterychip.com/en/product/AT32F423.jsp +at_start_f425 AT-START-F425 at32f425 https://www.arterychip.com/en/product/AT32F425.jsp +at_start_f437 AT-START-F437 at32f435_437 https://www.arterychip.com/en/product/AT32F437.jsp +============== ============== ============= ================================================== ====== + Bridgetek --------- @@ -326,6 +341,6 @@ ch32v103r_r1_1v0 CH32V103R-R1-1v1 ch32v10x https://github.com/openwch/ch32v10 ch32v203c_r0_1v0 CH32V203C-R0-1v0 ch32v20x https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0 ch32v203g_r0_1v0 CH32V203G-R0-1v0 ch32v20x https://github.com/openwch/ch32v20x/tree/main/SCHPCB/CH32V203C-R0 nanoch32v203 nanoCH32V203 ch32v20x https://github.com/wuxx/nanoCH32V203 -nanoch32v305 nanoCH32V305 ch32v30x https://github.com/wuxx/nanoCH32V305 ch32v307v_r1_1v0 CH32V307V-R1-1v0 ch32v30x https://github.com/openwch/ch32v307/tree/main/SCHPCB/CH32V307V-R1-1v0 +nanoch32v305 nanoCH32V305 ch32v30x https://github.com/wuxx/nanoCH32V305 ================ ================ ======== ===================================================================== ====== diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index 5104c6456..d75139aae 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -9,6 +9,13 @@ Local Path Repo ======================================== ================================================================ ======================================== ====================================================================================================================================================================================================================================================================================================================================================== hw/mcu/allwinner https://github.com/hathach/allwinner_driver.git 8e5e89e8e132c0fd90e72d5422e5d3d68232b756 fc100s hw/mcu/analog/msdk https://github.com/analogdevicesinc/msdk.git b20b398d3e5e2007594e54a74ba3d2a2e50ddd75 maxim +hw/mcu/artery/at32f402_405 https://github.com/ArteryTek/AT32F402_405_Firmware_Library.git 4424515c2663e82438654e0947695295df2abdfe at32f402_405 +hw/mcu/artery/at32f403a_407 https://github.com/ArteryTek/AT32F403A_407_Firmware_Library.git f2cb360c3d28fada76b374308b8c4c61d37a090b at32f403a_407 +hw/mcu/artery/at32f413 https://github.com/ArteryTek/AT32F413_Firmware_Library.git f6fe62dfec9fd40c5b63d92fc5ef2c2b5e77a450 at32f413 +hw/mcu/artery/at32f415 https://github.com/ArteryTek/AT32F415_Firmware_Library.git 716f545aa1290ff144ccf023a8e797b951e1bc8e at32f415 +hw/mcu/artery/at32f423 https://github.com/ArteryTek/AT32F423_Firmware_Library.git 2afa7f12852e57a9e8aab3a892c641e1a8635a18 at32f423 +hw/mcu/artery/at32f425 https://github.com/ArteryTek/AT32F425_Firmware_Library.git 620233e1357d5c1b7e2bde6b9dd5196822b91817 at32f425 +hw/mcu/artery/at32f435_437 https://github.com/ArteryTek/AT32F435_437_Firmware_Library.git 25439cc6650a8ae0345934e8707a5f38c7ae41f8 at32f435_437 hw/mcu/bridgetek/ft9xx/ft90x-sdk https://github.com/BRTSG-FOSS/ft90x-sdk.git 91060164afe239fcb394122e8bf9eb24d3194eb1 brtmm90x hw/mcu/broadcom https://github.com/adafruit/broadcom-peripherals.git 08370086080759ed54ac1136d62d2ad24c6fa267 broadcom_32bit broadcom_64bit hw/mcu/gd/nuclei-sdk https://github.com/Nuclei-Software/nuclei-sdk.git 7eb7bfa9ea4fbeacfafe1d5f77d5a0e6ed3922e7 gd32vf103 @@ -44,6 +51,7 @@ hw/mcu/st/cmsis_device_n6 https://github.com/STMicroelectronics/ hw/mcu/st/cmsis_device_u5 https://github.com/STMicroelectronics/cmsis_device_u5.git 5ad9797c54ec3e55eff770fc9b3cd4a1aefc1309 stm32u5 hw/mcu/st/cmsis_device_wb https://github.com/STMicroelectronics/cmsis_device_wb.git d6a7fa2e7de084f5e5e47f2ab88b022fe9b50e5a stm32wb hw/mcu/st/stm32-mfxstm32l152 https://github.com/STMicroelectronics/stm32-mfxstm32l152.git 7f4389efee9c6a655b55e5df3fceef5586b35f9b stm32h7 +hw/mcu/st/stm32-tcpp0203 https://github.com/STMicroelectronics/stm32-tcpp0203.git 9918655bff176ac3046ccf378b5c7bbbc6a38d15 stm32h7rs stm32n6 hw/mcu/st/stm32c0xx_hal_driver https://github.com/STMicroelectronics/stm32c0xx_hal_driver.git 41253e2f1d7ae4a4d0c379cf63f5bcf71fcf8eb3 stm32c0 hw/mcu/st/stm32f0xx_hal_driver https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git 0e95cd88657030f640a11e690a8a5186c7712ea5 stm32f0 hw/mcu/st/stm32f1xx_hal_driver https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git 1dd9d3662fb7eb2a7f7d3bc0a4c1dc7537915a29 stm32f1 @@ -67,7 +75,7 @@ hw/mcu/ti https://github.com/hathach/ti_driver.g hw/mcu/wch/ch32f20x https://github.com/openwch/ch32f20x.git 77c4095087e5ed2c548ec9058e655d0b8757663b ch32f20x hw/mcu/wch/ch32v103 https://github.com/openwch/ch32v103.git 7578cae0b21f86dd053a1f781b2fc6ab99d0ec17 ch32v10x hw/mcu/wch/ch32v20x https://github.com/openwch/ch32v20x.git c4c38f507e258a4e69b059ccc2dc27dde33cea1b ch32v20x -hw/mcu/wch/ch32v307 https://github.com/openwch/ch32v307.git 184f21b852cb95eed58e86e901837bc9fff68775 ch32v307 +hw/mcu/wch/ch32v307 https://github.com/openwch/ch32v307.git 184f21b852cb95eed58e86e901837bc9fff68775 ch32v30x lib/CMSIS_5 https://github.com/ARM-software/CMSIS_5.git 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32n6 stm32u5 stm32wb sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg tm4c lib/CMSIS_6 https://github.com/ARM-software/CMSIS_6.git b0bbb0423b278ca632cfe1474eb227961d835fd2 ra lib/FreeRTOS-Kernel https://github.com/FreeRTOS/FreeRTOS-Kernel.git cc0e0707c0c748713485b870bb980852b210877f all diff --git a/examples/device/net_lwip_webserver/skip.txt b/examples/device/net_lwip_webserver/skip.txt index 6f66efb53..6121f1f9d 100644 --- a/examples/device/net_lwip_webserver/skip.txt +++ b/examples/device/net_lwip_webserver/skip.txt @@ -15,7 +15,7 @@ mcu:STM32N6 family:broadcom_64bit family:broadcom_32bit family:espressif -board:AT_START_F425 +board:at_start_f425 board:curiosity_nano board:frdm_kl25z # lpc55 has weird error 'ncm_interface' causes a section type conflict with 'ntb_parameters' diff --git a/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.cmake b/hw/bsp/at32f402_405/boards/at_start_f405/board.cmake similarity index 100% rename from hw/bsp/at32f402_405/boards/AT_START_F402_405/board.cmake rename to hw/bsp/at32f402_405/boards/at_start_f405/board.cmake diff --git a/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.h b/hw/bsp/at32f402_405/boards/at_start_f405/board.h similarity index 98% rename from hw/bsp/at32f402_405/boards/AT_START_F402_405/board.h rename to hw/bsp/at32f402_405/boards/at_start_f405/board.h index 0061fd242..2d6cc3e57 100644 --- a/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.h +++ b/hw/bsp/at32f402_405/boards/at_start_f405/board.h @@ -24,6 +24,11 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + name: AT-START-F405 + url: https://www.arterychip.com/en/product/AT32F405.jsp +*/ + #ifndef BOARD_H_ #define BOARD_H_ diff --git a/hw/bsp/at32f402_405/boards/AT_START_F402_405/board.mk b/hw/bsp/at32f402_405/boards/at_start_f405/board.mk similarity index 100% rename from hw/bsp/at32f402_405/boards/AT_START_F402_405/board.mk rename to hw/bsp/at32f402_405/boards/at_start_f405/board.mk diff --git a/hw/bsp/at32f402_405/family.c b/hw/bsp/at32f402_405/family.c index 2dbc538b8..7d94f2564 100644 --- a/hw/bsp/at32f402_405/family.c +++ b/hw/bsp/at32f402_405/family.c @@ -24,6 +24,10 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + manufacturer: Artery +*/ + #include "at32f402_405_clock.h" #include "bsp/board_api.h" #include "board.h" diff --git a/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.cmake b/hw/bsp/at32f403a_407/boards/at_start_f403a/board.cmake similarity index 100% rename from hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.cmake rename to hw/bsp/at32f403a_407/boards/at_start_f403a/board.cmake diff --git a/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.h b/hw/bsp/at32f403a_407/boards/at_start_f403a/board.h similarity index 86% rename from hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.h rename to hw/bsp/at32f403a_407/boards/at_start_f403a/board.h index 55d9d05dc..472901cfe 100644 --- a/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.h +++ b/hw/bsp/at32f403a_407/boards/at_start_f403a/board.h @@ -24,6 +24,11 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + name: AT-START-F403a + url: https://www.arterychip.com/en/product/AT32F403.jsp +*/ + #ifndef BOARD_H_ #define BOARD_H_ @@ -37,6 +42,11 @@ #define LED_STATE_ON 0 // Active Low #define LED_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE) +// #define LED_PORT GPIOA +// #define LED_PIN GPIO_PINS_1 +// #define LED_STATE_ON 0 // Active Low +// #define LED_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) + // Button #define BUTTON_PORT GPIOA #define BUTTON_PIN GPIO_PINS_0 diff --git a/hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.mk b/hw/bsp/at32f403a_407/boards/at_start_f403a/board.mk similarity index 100% rename from hw/bsp/at32f403a_407/boards/AT_START_F403A_407/board.mk rename to hw/bsp/at32f403a_407/boards/at_start_f403a/board.mk diff --git a/hw/bsp/at32f403a_407/family.c b/hw/bsp/at32f403a_407/family.c index f9a6dd70d..b05a0435f 100644 --- a/hw/bsp/at32f403a_407/family.c +++ b/hw/bsp/at32f403a_407/family.c @@ -24,6 +24,10 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + manufacturer: Artery +*/ + #include "at32f403a_407_clock.h" #include "board.h" #include "bsp/board_api.h" diff --git a/hw/bsp/at32f413/boards/AT_START_F413/board.cmake b/hw/bsp/at32f413/boards/at_start_f413/board.cmake similarity index 100% rename from hw/bsp/at32f413/boards/AT_START_F413/board.cmake rename to hw/bsp/at32f413/boards/at_start_f413/board.cmake diff --git a/hw/bsp/at32f413/boards/AT_START_F413/board.h b/hw/bsp/at32f413/boards/at_start_f413/board.h similarity index 95% rename from hw/bsp/at32f413/boards/AT_START_F413/board.h rename to hw/bsp/at32f413/boards/at_start_f413/board.h index 13ec7a207..4b386a2f4 100644 --- a/hw/bsp/at32f413/boards/AT_START_F413/board.h +++ b/hw/bsp/at32f413/boards/at_start_f413/board.h @@ -24,6 +24,11 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + name: AT-START-F413 + url: https://www.arterychip.com/en/product/AT32F413.jsp +*/ + #ifndef BOARD_H_ #define BOARD_H_ diff --git a/hw/bsp/at32f413/boards/AT_START_F413/board.mk b/hw/bsp/at32f413/boards/at_start_f413/board.mk similarity index 100% rename from hw/bsp/at32f413/boards/AT_START_F413/board.mk rename to hw/bsp/at32f413/boards/at_start_f413/board.mk diff --git a/hw/bsp/at32f413/family.c b/hw/bsp/at32f413/family.c index 6e12c6015..bb16d4d5b 100644 --- a/hw/bsp/at32f413/family.c +++ b/hw/bsp/at32f413/family.c @@ -24,6 +24,10 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + manufacturer: Artery +*/ + #include "at32f413_clock.h" #include "board.h" #include "bsp/board_api.h" diff --git a/hw/bsp/at32f415/boards/AT_START_F415/board.cmake b/hw/bsp/at32f415/boards/at_start_f415/board.cmake similarity index 100% rename from hw/bsp/at32f415/boards/AT_START_F415/board.cmake rename to hw/bsp/at32f415/boards/at_start_f415/board.cmake diff --git a/hw/bsp/at32f415/boards/AT_START_F415/board.h b/hw/bsp/at32f415/boards/at_start_f415/board.h similarity index 96% rename from hw/bsp/at32f415/boards/AT_START_F415/board.h rename to hw/bsp/at32f415/boards/at_start_f415/board.h index 8b933f9e9..0464d383e 100644 --- a/hw/bsp/at32f415/boards/AT_START_F415/board.h +++ b/hw/bsp/at32f415/boards/at_start_f415/board.h @@ -24,6 +24,11 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + name: AT-START-F415 + url: https://www.arterychip.com/en/product/AT32F415.jsp +*/ + #ifndef BOARD_H_ #define BOARD_H_ diff --git a/hw/bsp/at32f415/boards/AT_START_F415/board.mk b/hw/bsp/at32f415/boards/at_start_f415/board.mk similarity index 100% rename from hw/bsp/at32f415/boards/AT_START_F415/board.mk rename to hw/bsp/at32f415/boards/at_start_f415/board.mk diff --git a/hw/bsp/at32f415/family.c b/hw/bsp/at32f415/family.c index b8ccae97d..381b79eeb 100644 --- a/hw/bsp/at32f415/family.c +++ b/hw/bsp/at32f415/family.c @@ -24,6 +24,10 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + manufacturer: Artery +*/ + #include "at32f415_clock.h" #include "board.h" #include "bsp/board_api.h" diff --git a/hw/bsp/at32f423/boards/AT_START_F423/board.cmake b/hw/bsp/at32f423/boards/at_start_f423/board.cmake similarity index 100% rename from hw/bsp/at32f423/boards/AT_START_F423/board.cmake rename to hw/bsp/at32f423/boards/at_start_f423/board.cmake diff --git a/hw/bsp/at32f423/boards/AT_START_F423/board.h b/hw/bsp/at32f423/boards/at_start_f423/board.h similarity index 97% rename from hw/bsp/at32f423/boards/AT_START_F423/board.h rename to hw/bsp/at32f423/boards/at_start_f423/board.h index fc8e2d8a5..ef85b4977 100644 --- a/hw/bsp/at32f423/boards/AT_START_F423/board.h +++ b/hw/bsp/at32f423/boards/at_start_f423/board.h @@ -24,6 +24,11 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + name: AT-START-F423 + url: https://www.arterychip.com/en/product/AT32F423.jsp +*/ + #ifndef BOARD_H_ #define BOARD_H_ diff --git a/hw/bsp/at32f423/boards/AT_START_F423/board.mk b/hw/bsp/at32f423/boards/at_start_f423/board.mk similarity index 100% rename from hw/bsp/at32f423/boards/AT_START_F423/board.mk rename to hw/bsp/at32f423/boards/at_start_f423/board.mk diff --git a/hw/bsp/at32f423/family.c b/hw/bsp/at32f423/family.c index 5e9e70dd8..723a8a2c9 100644 --- a/hw/bsp/at32f423/family.c +++ b/hw/bsp/at32f423/family.c @@ -24,6 +24,10 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + manufacturer: Artery +*/ + #include "at32f423_clock.h" #include "board.h" #include "bsp/board_api.h" diff --git a/hw/bsp/at32f425/boards/AT_START_F425/board.cmake b/hw/bsp/at32f425/boards/at_start_f425/board.cmake similarity index 100% rename from hw/bsp/at32f425/boards/AT_START_F425/board.cmake rename to hw/bsp/at32f425/boards/at_start_f425/board.cmake diff --git a/hw/bsp/at32f425/boards/AT_START_F425/board.h b/hw/bsp/at32f425/boards/at_start_f425/board.h similarity index 97% rename from hw/bsp/at32f425/boards/AT_START_F425/board.h rename to hw/bsp/at32f425/boards/at_start_f425/board.h index ddfe1f71b..145eab3b9 100644 --- a/hw/bsp/at32f425/boards/AT_START_F425/board.h +++ b/hw/bsp/at32f425/boards/at_start_f425/board.h @@ -24,6 +24,11 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + name: AT-START-F425 + url: https://www.arterychip.com/en/product/AT32F425.jsp +*/ + #ifndef BOARD_H_ #define BOARD_H_ diff --git a/hw/bsp/at32f425/boards/AT_START_F425/board.mk b/hw/bsp/at32f425/boards/at_start_f425/board.mk similarity index 100% rename from hw/bsp/at32f425/boards/AT_START_F425/board.mk rename to hw/bsp/at32f425/boards/at_start_f425/board.mk diff --git a/hw/bsp/at32f425/family.c b/hw/bsp/at32f425/family.c index 26e69bf31..963e1485f 100644 --- a/hw/bsp/at32f425/family.c +++ b/hw/bsp/at32f425/family.c @@ -24,6 +24,10 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + manufacturer: Artery +*/ + #include "at32f425_clock.h" #include "board.h" #include "bsp/board_api.h" diff --git a/hw/bsp/at32f435_437/boards/AT_START_F435_437/board.cmake b/hw/bsp/at32f435_437/boards/at_start_f437/board.cmake similarity index 100% rename from hw/bsp/at32f435_437/boards/AT_START_F435_437/board.cmake rename to hw/bsp/at32f435_437/boards/at_start_f437/board.cmake diff --git a/hw/bsp/at32f435_437/boards/AT_START_F435_437/board.h b/hw/bsp/at32f435_437/boards/at_start_f437/board.h similarity index 98% rename from hw/bsp/at32f435_437/boards/AT_START_F435_437/board.h rename to hw/bsp/at32f435_437/boards/at_start_f437/board.h index ef4ec6dcf..b6de119bc 100644 --- a/hw/bsp/at32f435_437/boards/AT_START_F435_437/board.h +++ b/hw/bsp/at32f435_437/boards/at_start_f437/board.h @@ -24,6 +24,11 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + name: AT-START-F437 + url: https://www.arterychip.com/en/product/AT32F437.jsp +*/ + #ifndef BOARD_H_ #define BOARD_H_ diff --git a/hw/bsp/at32f435_437/boards/AT_START_F435_437/board.mk b/hw/bsp/at32f435_437/boards/at_start_f437/board.mk similarity index 100% rename from hw/bsp/at32f435_437/boards/AT_START_F435_437/board.mk rename to hw/bsp/at32f435_437/boards/at_start_f437/board.mk diff --git a/hw/bsp/at32f435_437/family.c b/hw/bsp/at32f435_437/family.c index c93beeb5a..702fdd2a8 100644 --- a/hw/bsp/at32f435_437/family.c +++ b/hw/bsp/at32f435_437/family.c @@ -24,6 +24,10 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + manufacturer: Artery +*/ + #include "at32f435_437_clock.h" #include "board.h" #include "bsp/board_api.h" From f5974b041e858badab1fbf187926efa8b79367cd Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 1 Aug 2025 22:44:32 +0700 Subject: [PATCH 320/382] add bufsize to tud_msc_inquiry2_cb() --- examples/device/cdc_msc/src/msc_disk.c | 3 ++- examples/device/cdc_msc_freertos/src/msc_disk.c | 5 +++-- examples/device/dynamic_configuration/src/msc_disk.c | 3 ++- examples/device/msc_dual_lun/src/msc_disk_dual.c | 3 ++- src/class/msc/msc_device.c | 6 +++--- src/class/msc/msc_device.h | 2 +- test/unit-test/test/device/msc/test_msc_device.c | 3 ++- 7 files changed, 15 insertions(+), 10 deletions(-) diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index 6fd42dd80..96f9f19ec 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -119,8 +119,9 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { // Invoked when received SCSI_CMD_INQUIRY, v2 with full inquiry response // Some inquiry_resp's fields are already filled with default values, application can update them // Return length of inquiry response, typically sizeof(scsi_inquiry_resp_t) (36 bytes), can be longer if included vendor data. -uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t* inquiry_resp) { +uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t *inquiry_resp, uint32_t bufsize) { (void) lun; + (void) bufsize; const char vid[] = "TinyUSB"; const char pid[] = "Mass Storage"; const char rev[] = "1.0"; diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index 3a652103f..3602c991d 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -166,7 +166,7 @@ static void io_task(void *params) { io_ops_t io_ops; while (1) { if (xQueueReceive(io_queue, &io_ops, portMAX_DELAY)) { - const uint8_t* addr = msc_disk[io_ops.lba] + io_ops.offset; + uint8_t* addr = (uint8_t*) (uintptr_t) (msc_disk[io_ops.lba] + io_ops.offset); int32_t nbytes = io_ops.bufsize; if (io_ops.is_read) { memcpy(io_ops.buffer, addr, io_ops.bufsize); @@ -191,8 +191,9 @@ void msc_disk_init() {} // Invoked when received SCSI_CMD_INQUIRY, v2 with full inquiry response // Some inquiry_resp's fields are already filled with default values, application can update them // Return length of inquiry response, typically sizeof(scsi_inquiry_resp_t) (36 bytes), can be longer if included vendor data. -uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t* inquiry_resp) { +uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t* inquiry_resp, uint32_t bufsize) { (void) lun; + (void) bufsize; const char vid[] = "TinyUSB"; const char pid[] = "Mass Storage"; const char rev[] = "1.0"; diff --git a/examples/device/dynamic_configuration/src/msc_disk.c b/examples/device/dynamic_configuration/src/msc_disk.c index 8987c06be..ebc86e260 100644 --- a/examples/device/dynamic_configuration/src/msc_disk.c +++ b/examples/device/dynamic_configuration/src/msc_disk.c @@ -119,8 +119,9 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = // Invoked when received SCSI_CMD_INQUIRY, v2 with full inquiry response // Some inquiry_resp's fields are already filled with default values, application can update them // Return length of inquiry response, typically sizeof(scsi_inquiry_resp_t) (36 bytes), can be longer if included vendor data. -uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t* inquiry_resp) { +uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t *inquiry_resp, uint32_t bufsize) { (void) lun; + (void) bufsize; const char vid[] = "TinyUSB"; const char pid[] = "Mass Storage"; const char rev[] = "1.0"; diff --git a/examples/device/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c index a1ad220b3..98016808a 100644 --- a/examples/device/msc_dual_lun/src/msc_disk_dual.c +++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c @@ -210,8 +210,9 @@ uint8_t tud_msc_get_maxlun_cb(void) { // Invoked when received SCSI_CMD_INQUIRY, v2 with full inquiry response // Some inquiry_resp's fields are already filled with default values, application can update them // Return length of inquiry response, typically sizeof(scsi_inquiry_resp_t) (36 bytes), can be longer if included vendor data. -uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t* inquiry_resp) { +uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t *inquiry_resp, uint32_t bufsize) { (void) lun; + uint32_t bufsize const char vid[] = "TinyUSB"; const char pid[] = "Mass Storage"; const char rev[] = "1.0"; diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 3a4b34e7e..a32014c2d 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -47,8 +47,8 @@ TU_ATTR_WEAK void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) { (void) lun; (void) vendor_id; (void) product_id; (void) product_rev; } -TU_ATTR_WEAK uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t* inquiry_resp) { - (void) lun; (void) inquiry_resp; +TU_ATTR_WEAK uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t *inquiry_resp, uint32_t bufsize) { + (void) lun; (void) inquiry_resp; (void) bufsize; return 0; } @@ -749,7 +749,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_ inquiry_rsp->response_data_format = 2; inquiry_rsp->additional_length = sizeof(scsi_inquiry_resp_t) - 5; - resplen = (int32_t) tud_msc_inquiry2_cb(lun, inquiry_rsp); + resplen = (int32_t) tud_msc_inquiry2_cb(lun, inquiry_rsp, bufsize); if (resplen == 0) { // stub callback with no response, use v1 callback tud_msc_inquiry_cb(lun, inquiry_rsp->vendor_id, inquiry_rsp->product_id, inquiry_rsp->product_rev); diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 195c6fa87..144b74f71 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -97,7 +97,7 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16 // Invoked when received SCSI_CMD_INQUIRY, v2 with full inquiry response // Some inquiry_resp's fields are already filled with default values, application can update them // Return length of inquiry response, typically sizeof(scsi_inquiry_resp_t) (36 bytes), can be longer if included vendor data. -uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t* inquiry_resp); +uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t *inquiry_resp, uint32_t bufsize); // Invoked when received Test Unit Ready command. // return true allowing host to read/write this LUN e.g SD card inserted diff --git a/test/unit-test/test/device/msc/test_msc_device.c b/test/unit-test/test/device/msc/test_msc_device.c index e05e9c8b0..49843a921 100644 --- a/test/unit-test/test/device/msc/test_msc_device.c +++ b/test/unit-test/test/device/msc/test_msc_device.c @@ -97,8 +97,9 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE]; // Invoked when received SCSI_CMD_INQUIRY, v2 with full inquiry response // Some inquiry_resp's fields are already filled with default values, application can update them // Return length of inquiry response, typically sizeof(scsi_inquiry_resp_t) (36 bytes), can be longer if included vendor data. -uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t* inquiry_resp) { +uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t* inquiry_resp, uint32_t bufsize) { (void) lun; + (void) bufsize; const char vid[] = "TinyUSB"; const char pid[] = "Mass Storage"; const char rev[] = "1.0"; From f66f98f442f1a494e6238a35b3ecd751e0568b70 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Fri, 1 Aug 2025 22:56:00 +0700 Subject: [PATCH 321/382] Update examples/device/msc_dual_lun/src/msc_disk_dual.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- examples/device/msc_dual_lun/src/msc_disk_dual.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/device/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c index 98016808a..775fa047e 100644 --- a/examples/device/msc_dual_lun/src/msc_disk_dual.c +++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c @@ -212,7 +212,7 @@ uint8_t tud_msc_get_maxlun_cb(void) { // Return length of inquiry response, typically sizeof(scsi_inquiry_resp_t) (36 bytes), can be longer if included vendor data. uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t *inquiry_resp, uint32_t bufsize) { (void) lun; - uint32_t bufsize + (void) bufsize; const char vid[] = "TinyUSB"; const char pid[] = "Mass Storage"; const char rev[] = "1.0"; From 12a1d0e7ede97c793a5e11b3cce7284cdbe994c8 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 2 Aug 2025 11:23:15 +0700 Subject: [PATCH 322/382] use tu_desc_in_bounds() for descriptor loop --- src/class/midi/midi_host.c | 19 ++++++++------- src/class/vendor/vendor_device.c | 2 +- src/common/tusb_common.h | 38 ++++++++++++++++++++++++++++++ src/common/tusb_types.h | 40 -------------------------------- 4 files changed, 49 insertions(+), 50 deletions(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 2395a0ef8..50bda1e36 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -197,6 +197,7 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint //--------------------------------------------------------------------+ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void) rhport; + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); const uint8_t *p_end = ((const uint8_t *) desc_itf) + max_len; const uint8_t *p_desc = (const uint8_t *) desc_itf; @@ -210,9 +211,8 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d desc_cb.jack_num = 0; // There can be just a MIDI or an Audio + MIDI interface - // If there is Audio Control Interface + Audio Header descriptor, then skip it. - // If there is an Audio Control Interface + Audio Streaming Interface, then - // ignore the Audio Streaming Interface. + // - If there is Audio Control Interface + Audio Header descriptor, then skip it. + // - If there is an Audio Control Interface + Audio Streaming Interface, then ignore the Audio Streaming Interface. // Future: // Note that if this driver is used with an USB Audio Streaming host driver, // then call that driver first. If the MIDI interface comes before the @@ -230,19 +230,20 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d p_desc = tu_desc_next(p_desc); desc_itf = (const tusb_desc_interface_t *)p_desc; p_midi->itf_count = 1; - // See issue #3159 - while ((p_desc < p_end) && (tu_desc_next(p_desc) <= p_end) && (desc_itf->bDescriptorType != TUSB_DESC_INTERFACE || (desc_itf->bInterfaceClass == TUSB_CLASS_AUDIO && desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING))) - { + // skip non-interface and non-midi streaming descriptors + while (tu_desc_in_bounds(p_desc, p_end) && + (desc_itf->bDescriptorType != TUSB_DESC_INTERFACE || (desc_itf->bInterfaceClass == TUSB_CLASS_AUDIO && desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING))) { if (desc_itf->bDescriptorType == TUSB_DESC_INTERFACE && desc_itf->bAlternateSetting == 0) { p_midi->itf_count++; } p_desc = tu_desc_next(p_desc); desc_itf = (tusb_desc_interface_t const *)p_desc; } - TU_VERIFY(p_desc < p_end); // If MIDI interface comes after Audio Streaming, then max_len did not include the MIDI interface descriptor + TU_VERIFY(p_desc < p_end); // TODO: If MIDI interface comes after Audio Streaming, then max_len did not include the MIDI interface descriptor TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); -} + } TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass); + TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); p_midi->bInterfaceNumber = desc_itf->bInterfaceNumber; p_midi->iInterface = desc_itf->iInterface; @@ -252,7 +253,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d p_desc = tu_desc_next(p_desc); // next to CS Header bool found_new_interface = false; - while ((p_desc < p_end) && (tu_desc_next(p_desc) <= p_end) && !found_new_interface) { + while (tu_desc_in_bounds(p_desc, p_end) && !found_new_interface) { switch (tu_desc_type(p_desc)) { case TUSB_DESC_INTERFACE: found_new_interface = true; diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 6f109c321..b0332b0fe 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -211,7 +211,7 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin TU_VERIFY(p_vendor, 0); p_vendor->itf_num = desc_itf->bInterfaceNumber; - while (tu_desc_is_valid(p_desc, desc_end)) { + while (tu_desc_in_bounds(p_desc, desc_end)) { const uint8_t desc_type = tu_desc_type(p_desc); if (desc_type == TUSB_DESC_INTERFACE || desc_type == TUSB_DESC_INTERFACE_ASSOCIATION) { break; // end of this interface diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 0351a3d8f..489e09a15 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -324,6 +324,44 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_ + TU_BIN8(dlsb)) #endif +//--------------------------------------------------------------------+ +// Descriptor helper +//--------------------------------------------------------------------+ + +// return next descriptor +TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) { + uint8_t const* desc8 = (uint8_t const*) desc; + return desc8 + desc8[DESC_OFFSET_LEN]; +} + +// get descriptor length +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) { + return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; +} + +// get descriptor type +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) { + return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; +} + +// get descriptor subtype +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) { + return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE]; +} + +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_in_bounds(uint8_t const* p_desc, uint8_t const* desc_end) { + return (p_desc < desc_end) && (tu_desc_next(p_desc) <= desc_end); +} + +// find descriptor that match byte1 (type) +uint8_t const * tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1); + +// find descriptor that match byte1 (type) and byte2 +uint8_t const * tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2); + +// find descriptor that match byte1 (type) and byte2 +uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3); + #ifdef __cplusplus } #endif diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ee97069bd..b3ef1e9c9 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -562,46 +562,6 @@ TU_ATTR_ALWAYS_INLINE static inline const char *tu_edpt_type_str(tusb_xfer_type_ } #endif -//--------------------------------------------------------------------+ -// Descriptor helper -//--------------------------------------------------------------------+ - -// return next descriptor -TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* desc) { - uint8_t const* desc8 = (uint8_t const*) desc; - return desc8 + desc8[DESC_OFFSET_LEN]; -} - -// get descriptor length -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) { - return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; -} - -// get descriptor type -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) { - return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; -} - -// get descriptor subtype -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) { - return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE]; -} - -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_is_valid(void const* desc, uint8_t const* desc_end) { - const uint8_t* desc8 = (uint8_t const*) desc; - return (desc8 < desc_end) && (tu_desc_next(desc) <= desc_end); -} - - -// find descriptor that match byte1 (type) -uint8_t const * tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1); - -// find descriptor that match byte1 (type) and byte2 -uint8_t const * tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2); - -// find descriptor that match byte1 (type) and byte2 -uint8_t const * tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3); - #ifdef __cplusplus } #endif From d9aa4c6f6184eacafb534bf462d7a90ca71aeac9 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 2 Aug 2025 23:23:20 +0700 Subject: [PATCH 323/382] fix tud_audio_set_itf_close_EP_cb() typo --- examples/device/audio_test/src/main.c | 2 +- examples/device/audio_test_freertos/src/main.c | 2 +- examples/device/audio_test_multi_rate/src/main.c | 2 +- examples/device/cdc_uac2/src/uac2_app.c | 2 +- examples/device/uac2_headset/src/main.c | 2 +- examples/device/uac2_speaker_fb/src/main.c | 2 +- src/class/audio/audio_device.c | 6 +++--- src/class/audio/audio_device.h | 5 ++++- 8 files changed, 13 insertions(+), 10 deletions(-) diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 07728e24a..ec47de7b8 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -386,7 +386,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p return false;// Yet not implemented } -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request) { +bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; (void) p_request; startVal = 0; diff --git a/examples/device/audio_test_freertos/src/main.c b/examples/device/audio_test_freertos/src/main.c index b1119c888..b2bed295f 100644 --- a/examples/device/audio_test_freertos/src/main.c +++ b/examples/device/audio_test_freertos/src/main.c @@ -457,7 +457,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p return false;// Yet not implemented } -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request) { +bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; (void) p_request; startVal = 0; diff --git a/examples/device/audio_test_multi_rate/src/main.c b/examples/device/audio_test_multi_rate/src/main.c index 704a75b09..87f56f4b5 100644 --- a/examples/device/audio_test_multi_rate/src/main.c +++ b/examples/device/audio_test_multi_rate/src/main.c @@ -455,7 +455,7 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p return false;// Yet not implemented } -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request) { +bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; (void) p_request; startVal = 0; diff --git a/examples/device/cdc_uac2/src/uac2_app.c b/examples/device/cdc_uac2/src/uac2_app.c index 7d5da5ed0..a1a0dd73d 100644 --- a/examples/device/cdc_uac2/src/uac2_app.c +++ b/examples/device/cdc_uac2/src/uac2_app.c @@ -257,7 +257,7 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p return false; } -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request) +bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request) { (void)rhport; diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 33b8ea0ef..06a673f91 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -291,7 +291,7 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p return false; } -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request) { +bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); diff --git a/examples/device/uac2_speaker_fb/src/main.c b/examples/device/uac2_speaker_fb/src/main.c index 12425b919..d9f6e9259 100644 --- a/examples/device/uac2_speaker_fb/src/main.c +++ b/examples/device/uac2_speaker_fb/src/main.c @@ -299,7 +299,7 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p return false; } -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request) { +bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 278c4514a..bb906c7cf 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -402,7 +402,7 @@ TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t co } // Invoked when audio set interface request received which closes an EP -TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const *p_request) { +TU_ATTR_WEAK bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const *p_request) { (void) rhport; (void) p_request; return true; @@ -1078,7 +1078,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p tu_fifo_clear(&audio->ep_in_ff); // Invoke callback - can be used to stop data sampling - TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + TU_VERIFY(tud_audio_set_itf_close_ep_cb(rhport, p_request)); audio->ep_in = 0;// Necessary? @@ -1101,7 +1101,7 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p tu_fifo_clear(&audio->ep_out_ff); // Invoke callback - can be used to stop data sampling - TU_VERIFY(tud_audio_set_itf_close_EP_cb(rhport, p_request)); + TU_VERIFY(tud_audio_set_itf_close_ep_cb(rhport, p_request)); audio->ep_out = 0;// Necessary? diff --git a/src/class/audio/audio_device.h b/src/class/audio/audio_device.h index 307389418..6bcedc88c 100644 --- a/src/class/audio/audio_device.h +++ b/src/class/audio/audio_device.h @@ -381,7 +381,10 @@ void tud_audio_int_done_cb(uint8_t rhport); bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request); // Invoked when audio set interface request received which closes an EP -bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request); +bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request); + +// backward compatible for typo +#define tud_audio_set_itf_close_EP_cb tud_audio_set_itf_close_ep_cb // Invoked when audio class specific set request received for an EP bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff); From 2298c2f410faaf3016ae0e43aa51be869d502bc9 Mon Sep 17 00:00:00 2001 From: peppapighs Date: Tue, 5 Aug 2025 18:17:27 +0700 Subject: [PATCH 324/382] Fix AT32F405xx missing USB HS definition --- src/common/tusb_mcu.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index a91759b84..6632341d7 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -601,6 +601,15 @@ #define TUP_USBIP_DWC2_AT32 #define TUP_DCD_ENDPOINT_MAX 8 + // AT32F405xx has on-chip HS PHY + #if defined(AT32F405CBT7) || defined(AT32F405CBU7) || \ + defined(AT32F405CCT7) || defined(AT32F405CCU7) || \ + defined(AT32F405KBU7_4) || defined(AT32F405KCU7_4) || \ + defined(AT32F405RBT7_7) || defined(AT32F405RBT7) || \ + defined(AT32F405RCT7_7) || defined(AT32F405RCT7) + #define TUP_RHPORT_HIGHSPEED 1 // Port0: FS, Port1: HS + #endif + #elif TU_CHECK_MCU(OPT_MCU_AT32F425) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_AT32 From 4bfba6b09a90d5321b3dbd2d986760438417c430 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 5 Aug 2025 22:05:56 +0700 Subject: [PATCH 325/382] fix rp2 iso transfer: reset state before notify stack. since new audio driver can execute xfer_is() --- examples/device/uac2_headset/src/main.c | 6 ++++-- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 06a673f91..d4c2b41d9 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -297,8 +297,9 @@ bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const uint8_t const itf = tu_u16_low(tu_le16toh(p_request->wIndex)); uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); - if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt == 0) + if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt == 0) { blink_interval_ms = BLINK_MOUNTED; + } return true; } @@ -309,8 +310,9 @@ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_reques uint8_t const alt = tu_u16_low(tu_le16toh(p_request->wValue)); TU_LOG2("Set interface %d alt %d\r\n", itf, alt); - if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt != 0) + if (ITF_NUM_AUDIO_STREAMING_SPK == itf && alt != 0) { blink_interval_ms = BLINK_STREAMING; + } // Clear buffer when streaming format is changed spk_data_size = 0; diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 358ce84bc..a89c2f42b 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -190,8 +190,9 @@ static void __tusb_irq_path_func(hw_handle_buff_status)(void) { bool done = hw_endpoint_xfer_continue(ep); if (done) { // Notify - dcd_event_xfer_complete(0, ep->ep_addr, ep->xferred_len, XFER_RESULT_SUCCESS, true); + const uint16_t xferred_len = ep->xferred_len; hw_endpoint_reset_transfer(ep); + dcd_event_xfer_complete(0, ep->ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); } remaining_buffers &= ~bit; } From 5b9908a39ba089dfd56b3a23475be5d9691d13e8 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 7 Aug 2025 14:20:40 +0700 Subject: [PATCH 326/382] update at32f405 dwc2 info and phy width selection --- src/portable/synopsys/dwc2/dwc2_common.c | 24 ++--- src/portable/synopsys/dwc2/dwc2_info.md | 116 +++++++++++------------ src/portable/synopsys/dwc2/dwc2_info.py | 2 + 3 files changed, 72 insertions(+), 70 deletions(-) diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index b001f343d..70876a64c 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -92,6 +92,14 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; const dwc2_ghwcfg4_t ghwcfg4 = {.value = dwc2->ghwcfg4}; + uint8_t phy_width; + if (CFG_TUSB_MCU != OPT_MCU_AT32F402_405 && // at32f402_405 does not support 16-bit + ghwcfg4.phy_data_width) { + phy_width = 16; // 16-bit PHY interface if supported + } else { + phy_width = 8; // 8-bit PHY interface + } + // De-select FS PHY gusbcfg &= ~GUSBCFG_PHYSEL; @@ -119,12 +127,10 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { gusbcfg &= ~GUSBCFG_ULPI_UTMI_SEL; // Set 16-bit interface if supported - if (ghwcfg4.phy_data_width) { - #if CFG_TUSB_MCU != OPT_MCU_AT32F402_405 // at32f402_405 does not actually support 16-bit - gusbcfg |= GUSBCFG_PHYIF16; // 16 bit - #endif + if (phy_width == 16) { + gusbcfg |= GUSBCFG_PHYIF16; } else { - gusbcfg &= ~GUSBCFG_PHYIF16; // 8 bit + gusbcfg &= ~GUSBCFG_PHYIF16; } } @@ -141,13 +147,7 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { // - 9 if using 8-bit PHY interface // - 5 if using 16-bit PHY interface gusbcfg &= ~GUSBCFG_TRDT_Msk; - -#if CFG_TUSB_MCU == OPT_MCU_AT32F402_405 // at32f402_405 does not actually support 16-bit - gusbcfg |= 9u << GUSBCFG_TRDT_Pos; -#else - gusbcfg |= (dwc2->ghwcfg4_bm.phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos; -#endif - + gusbcfg |= (phy_width == 16 ? 5u : 9u) << GUSBCFG_TRDT_Pos; dwc2->gusbcfg = gusbcfg; // MCU specific PHY update post reset diff --git a/src/portable/synopsys/dwc2/dwc2_info.md b/src/portable/synopsys/dwc2/dwc2_info.md index 595c89b75..00685e7ad 100644 --- a/src/portable/synopsys/dwc2/dwc2_info.md +++ b/src/portable/synopsys/dwc2/dwc2_info.md @@ -1,58 +1,58 @@ -| | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5/H7RS/N6 HS | XMC4500 | GD32VF103 | -|:---------------------------|:----------------|:-------------|:--------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:---------------------|:-------------|:------------| -| GUID | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00AEC000 | 0x00001000 | -| GSNPSID | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54292A | 0x00000000 | -| - specs version | 2.80a | 3.30a | 4.00a | 4.00a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 2.92a | 0.00W | -| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | -| GHWCFG2 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228F5930 | 0x00000000 | -| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | HNP SRP | HNP SRP | -| - arch | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | Slave only | -| - single_point | hub | hub | n/a | hub | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | n/a | hub | -| - hs_phy_type | UTMI+ | n/a | n/a | UTMI+/ULPI | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | n/a | n/a | -| - fs_phy_type | Dedicated | Dedicated | Dedicated | Shared ULPI | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | Dedicated | n/a | -| - num_dev_ep | 7 | 6 | 6 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | -| - num_host_ch | 7 | 13 | 7 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 13 | 0 | -| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - mul_proc_intrpt | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - nptx_q_depth | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - ptx_q_depth | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | -| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| GHWCFG3 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | -| - xfer_size_width | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | -| - packet_size_width | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | -| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - i2c_enable | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | -| - vendor_ctrl_itf | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | -| - optional_feature_removed | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - synch_reset | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - otg_adp_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - battery_charger_support | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | -| - dfifo_depth | 4080 | 498 | 200 | 896 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 634 | 0 | -| GHWCFG4 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | -| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - partial_powerdown | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - enhanced_lpm_support | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - phy_data_width | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8/16 bit | 8 bit | -| - ctrl_ep_num | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - iddg_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - vbus_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - a_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - b_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - session_end_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - num_dev_in_eps | 7 | 6 | 4 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | -| - dma_desc_enable | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | -| - dma_desc_dynamic | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | +| | AT32 F405 FS | AT32 F405 HS | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5/H7RS/N6 HS | XMC4500 | GD32VF103 | +|:---------------------------|:---------------|:---------------|:----------------|:-------------|:--------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:---------------------|:-------------|:------------| +| GUID | 0x00002000 | 0x00000000 | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00AEC000 | 0x00001000 | +| GSNPSID | 0x4F54400A | 0x4F54400A | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54292A | 0x00000000 | +| - specs version | 4.00a | 4.00a | 2.80a | 3.30a | 4.00a | 4.00a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 2.92a | 0.00W | +| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | +| GHWCFG2 | 0x228FDD00 | 0x229FDDD0 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228F5930 | 0x00000000 | +| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | HNP SRP | HNP SRP | +| - arch | Slave only | DMA internal | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | Slave only | +| - single_point | hub | hub | hub | hub | n/a | hub | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | n/a | hub | +| - hs_phy_type | n/a | UTMI+/ULPI | UTMI+ | n/a | n/a | UTMI+/ULPI | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | n/a | n/a | +| - fs_phy_type | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Shared ULPI | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | Dedicated | n/a | +| - num_dev_ep | 7 | 7 | 7 | 6 | 6 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | +| - num_host_ch | 15 | 15 | 7 | 13 | 7 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 13 | 0 | +| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - mul_proc_intrpt | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - nptx_q_depth | 8 | 8 | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - ptx_q_depth | 8 | 8 | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | +| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| GHWCFG3 | 0x020004E8 | 0x03F006E8 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | +| - xfer_size_width | 8 | 8 | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | +| - packet_size_width | 6 | 6 | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | +| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - i2c_enable | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | +| - vendor_ctrl_itf | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | +| - optional_feature_removed | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - synch_reset | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - otg_adp_support | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - battery_charger_support | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | +| - dfifo_depth | 512 | 1008 | 4080 | 498 | 200 | 896 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 634 | 0 | +| GHWCFG4 | 0x1FF0A020 | 0x1FF0A020 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | +| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - partial_powerdown | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - enhanced_lpm_support | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - phy_data_width | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8/16 bit | 8 bit | +| - ctrl_ep_num | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - iddg_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - vbus_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - a_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - b_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - session_end_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - num_dev_in_eps | 7 | 7 | 7 | 6 | 4 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | +| - dma_desc_enable | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | +| - dma_desc_dynamic | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py index 3b1993cc5..bc5ad9a7b 100755 --- a/src/portable/synopsys/dwc2/dwc2_info.py +++ b/src/portable/synopsys/dwc2/dwc2_info.py @@ -9,6 +9,8 @@ import pandas as pd # Note: FS is FullSpeed, HS is HighSpeed dwc2_reg_list = ['GUID', 'GSNPSID', 'GHWCFG1', 'GHWCFG2', 'GHWCFG3', 'GHWCFG4'] dwc2_reg_value = { + 'AT32 F405 FS': [0x00002000, 0x4F54400A, 0x00000000, 0x228FDD00, 0x020004E8, 0x1FF0A020], + 'AT32 F405 HS': [0x00000000, 0x4F54400A, 0x00000000, 0x229FDDD0, 0x03F006E8, 0x1FF0A020], 'BCM2711 (Pi4)': [0x2708A000, 0x4F54280A, 0, 0x228DDD50, 0xFF000E8, 0x1FF00020], 'EFM32GG': [0, 0x4F54330A, 0, 0x228F5910, 0x01F204E8, 0x1BF08030], 'ESP32-S2/S3': [0, 0x4F54400A, 0, 0x224DD930, 0x0C804B5, 0xD3F0A030], From 7142818abecca803bda7f31c3bfc1e5bd9eec51d Mon Sep 17 00:00:00 2001 From: Martijn van der Woude Date: Sat, 9 Aug 2025 10:41:03 +0200 Subject: [PATCH 327/382] Fix STM32L4 GPIOD clock enable for variants without GPIOD --- hw/bsp/stm32l4/family.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/bsp/stm32l4/family.c b/hw/bsp/stm32l4/family.c index 2b555b5c2..5c6ba5c61 100644 --- a/hw/bsp/stm32l4/family.c +++ b/hw/bsp/stm32l4/family.c @@ -59,7 +59,9 @@ void board_init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); +#if defined(GPIOD) __HAL_RCC_GPIOD_CLK_ENABLE(); +#endif #if defined(GPIOE) __HAL_RCC_GPIOE_CLK_ENABLE(); #endif From 836f887a23652cc397c996c005d8346c8d306fe1 Mon Sep 17 00:00:00 2001 From: Jie Feng Date: Sun, 10 Aug 2025 13:20:34 +0800 Subject: [PATCH 328/382] Add weact blackpill support --- .../at32f403a_weact_blackpill/board.cmake | 8 +++ .../boards/at32f403a_weact_blackpill/board.h | 67 +++++++++++++++++++ .../boards/at32f403a_weact_blackpill/board.mk | 7 ++ .../boards/at_start_f403a/board.h | 3 +- hw/bsp/at32f403a_407/family.c | 4 +- 5 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.cmake create mode 100644 hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h create mode 100644 hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.mk diff --git a/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.cmake b/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.cmake new file mode 100644 index 000000000..25c9558f9 --- /dev/null +++ b/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.cmake @@ -0,0 +1,8 @@ +set(MCU_VARIANT AT32F403ACGU7) +set(MCU_LINKER_NAME AT32F403AxG) + +set(JLINK_DEVICE ${MCU_VARIANT}) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC ${MCU_VARIANT}) +endfunction() diff --git a/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h b/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h new file mode 100644 index 000000000..73b6f91c1 --- /dev/null +++ b/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h @@ -0,0 +1,67 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: WeAct Studio BlackPill AT32F403ACGx + url: https://github.com/WeActStudio/WeActStudio.BlackPill +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PORT GPIOC +#define LED_PIN GPIO_PINS_13 +#define LED_STATE_ON 0 // Active Low +#define LED_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE) + +// Button +#define BUTTON_PORT GPIOA +#define BUTTON_PIN GPIO_PINS_0 +#define BUTTON_PULL GPIO_PULL_UP +#define BUTTON_STATE_ACTIVE 0 +#define BUTTON_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) + +// UART +#define PRINT_UART USART1 +#define PRINT_UART_CRM_CLK CRM_USART1_PERIPH_CLOCK +#define PRINT_UART_TX_PIN GPIO_PINS_9 +#define PRINT_UART_TX_GPIO GPIOA +#define PRINT_UART_TX_GPIO_CRM_CLK CRM_GPIOA_PERIPH_CLOCK + +static inline void board_vbus_sense_init(void) +{ +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.mk b/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.mk new file mode 100644 index 000000000..9bb6843aa --- /dev/null +++ b/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.mk @@ -0,0 +1,7 @@ +MCU_VARIANT = AT32F403ACGU7 +MCU_LINKER_NAME = AT32F403AxG + +JLINK_DEVICE = ${MCU_VARIANT} + +CFLAGS += \ + -D${MCU_VARIANT} diff --git a/hw/bsp/at32f403a_407/boards/at_start_f403a/board.h b/hw/bsp/at32f403a_407/boards/at_start_f403a/board.h index 472901cfe..758ab5e5c 100644 --- a/hw/bsp/at32f403a_407/boards/at_start_f403a/board.h +++ b/hw/bsp/at32f403a_407/boards/at_start_f403a/board.h @@ -50,7 +50,8 @@ // Button #define BUTTON_PORT GPIOA #define BUTTON_PIN GPIO_PINS_0 -#define BUTTON_STATE_ACTIVE 0 +#define BUTTON_PULL GPIO_PULL_DOWN +#define BUTTON_STATE_ACTIVE 1 #define BUTTON_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) // UART diff --git a/hw/bsp/at32f403a_407/family.c b/hw/bsp/at32f403a_407/family.c index b05a0435f..afd3a24d1 100644 --- a/hw/bsp/at32f403a_407/family.c +++ b/hw/bsp/at32f403a_407/family.c @@ -102,7 +102,7 @@ void board_init(void) { gpio_button_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_button_init_struct.gpio_mode = GPIO_MODE_INPUT; gpio_button_init_struct.gpio_pins = BUTTON_PIN; - gpio_button_init_struct.gpio_pull = GPIO_PULL_DOWN; + gpio_button_init_struct.gpio_pull = BUTTON_PULL; gpio_init(BUTTON_PORT, &gpio_button_init_struct); uart_print_init(115200); @@ -198,7 +198,7 @@ void board_led_write(bool state) { } uint32_t board_button_read(void) { - return gpio_input_data_bit_read(BUTTON_PORT, BUTTON_PIN); + return gpio_input_data_bit_read(BUTTON_PORT, BUTTON_PIN) == BUTTON_STATE_ACTIVE; } size_t board_get_unique_id(uint8_t id[], size_t max_len) { From 4a78e4c86193c562c684a7e445276982ae9a7cd5 Mon Sep 17 00:00:00 2001 From: Jie Feng Date: Sun, 10 Aug 2025 13:29:41 +0800 Subject: [PATCH 329/382] Add to boards.rst file --- docs/reference/boards.rst | 23 ++++++++++--------- .../boards/at32f403a_weact_blackpill/board.h | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 289ec543a..d35cf7b06 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -30,17 +30,18 @@ max78002evkit MAX78002 EVKIT maxim https://www.analog.com/en/resources/e Artery ----- -============== ============== ============= ================================================== ====== -Board Name Family URL Note -============== ============== ============= ================================================== ====== -at_start_f405 AT-START-F405 at32f402_405 https://www.arterychip.com/en/product/AT32F405.jsp -at_start_f403a AT-START-F403a at32f403a_407 https://www.arterychip.com/en/product/AT32F403.jsp -at_start_f413 AT-START-F413 at32f413 https://www.arterychip.com/en/product/AT32F413.jsp -at_start_f415 AT-START-F415 at32f415 https://www.arterychip.com/en/product/AT32F415.jsp -at_start_f423 AT-START-F423 at32f423 https://www.arterychip.com/en/product/AT32F423.jsp -at_start_f425 AT-START-F425 at32f425 https://www.arterychip.com/en/product/AT32F425.jsp -at_start_f437 AT-START-F437 at32f435_437 https://www.arterychip.com/en/product/AT32F437.jsp -============== ============== ============= ================================================== ====== +============== ============== ============= ================================================== ====== +Board Name Family URL Note +============== ============== ============= ================================================== ====== +at_start_f405 AT-START-F405 at32f402_405 https://www.arterychip.com/en/product/AT32F405.jsp +at_start_f403a AT-START-F403a at32f403a_407 https://www.arterychip.com/en/product/AT32F403.jsp +at32f403a_weact_blackpill WeAct Studio BlackPill AT32F403ACGU7 at32f403a_407 https://github.com/WeActStudio/WeActStudio.BlackPill +at_start_f413 AT-START-F413 at32f413 https://www.arterychip.com/en/product/AT32F413.jsp +at_start_f415 AT-START-F415 at32f415 https://www.arterychip.com/en/product/AT32F415.jsp +at_start_f423 AT-START-F423 at32f423 https://www.arterychip.com/en/product/AT32F423.jsp +at_start_f425 AT-START-F425 at32f425 https://www.arterychip.com/en/product/AT32F425.jsp +at_start_f437 AT-START-F437 at32f435_437 https://www.arterychip.com/en/product/AT32F437.jsp +============== ============== ============= ================================================== ====== Bridgetek --------- diff --git a/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h b/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h index 73b6f91c1..005c5aed6 100644 --- a/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h +++ b/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h @@ -25,7 +25,7 @@ */ /* metadata: - name: WeAct Studio BlackPill AT32F403ACGx + name: WeAct Studio BlackPill AT32F403ACGU7 url: https://github.com/WeActStudio/WeActStudio.BlackPill */ From 24e596b977f8e17e2c672cbbf8c337ced38a4788 Mon Sep 17 00:00:00 2001 From: Jie Feng Date: Sun, 10 Aug 2025 13:33:51 +0800 Subject: [PATCH 330/382] Fix file --- docs/reference/boards.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index d35cf7b06..f4f2f6d1f 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -30,9 +30,9 @@ max78002evkit MAX78002 EVKIT maxim https://www.analog.com/en/resources/e Artery ----- -============== ============== ============= ================================================== ====== -Board Name Family URL Note -============== ============== ============= ================================================== ====== +========================= ==================================== ============= ==================================================== ====== +Board Name Family URL Note +========================= ==================================== ============= ==================================================== ====== at_start_f405 AT-START-F405 at32f402_405 https://www.arterychip.com/en/product/AT32F405.jsp at_start_f403a AT-START-F403a at32f403a_407 https://www.arterychip.com/en/product/AT32F403.jsp at32f403a_weact_blackpill WeAct Studio BlackPill AT32F403ACGU7 at32f403a_407 https://github.com/WeActStudio/WeActStudio.BlackPill @@ -41,7 +41,7 @@ at_start_f415 AT-START-F415 at32f415 at_start_f423 AT-START-F423 at32f423 https://www.arterychip.com/en/product/AT32F423.jsp at_start_f425 AT-START-F425 at32f425 https://www.arterychip.com/en/product/AT32F425.jsp at_start_f437 AT-START-F437 at32f435_437 https://www.arterychip.com/en/product/AT32F437.jsp -============== ============== ============= ================================================== ====== +========================= ==================================== ============= ==================================================== ====== Bridgetek --------- From ddb8f0fe73fd733b0fd97462b14825dcb6039949 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 15 Aug 2025 10:15:24 -0700 Subject: [PATCH 331/382] Add ESP32-C5 and ESP32-C61 definitions --- src/common/tusb_mcu.h | 2 +- src/tusb_option.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 6632341d7..3ffc2d1a4 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -414,7 +414,7 @@ #define CFG_TUH_MEM_DCACHE_ENABLE_DEFAULT CFG_TUH_DWC2_DMA_ENABLE #define CFG_TUSB_MEM_DCACHE_LINE_SIZE_DEFAULT 64 -#elif TU_CHECK_MCU(OPT_MCU_ESP32, OPT_MCU_ESP32C2, OPT_MCU_ESP32C3, OPT_MCU_ESP32C6, OPT_MCU_ESP32H2) +#elif TU_CHECK_MCU(OPT_MCU_ESP32, OPT_MCU_ESP32C2, OPT_MCU_ESP32C3, OPT_MCU_ESP32C5, OPT_MCU_ESP32C6, OPT_MCU_ESP32C61, OPT_MCU_ESP32H2) #if (CFG_TUD_ENABLED || !(defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)) #error "MCUs are only supported with CFG_TUH_MAX3421 enabled" #endif diff --git a/src/tusb_option.h b/src/tusb_option.h index 17bf556a3..1533bb209 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -128,6 +128,8 @@ #define OPT_MCU_ESP32C2 905 ///< Espressif ESP32-C2 #define OPT_MCU_ESP32H2 906 ///< Espressif ESP32-H2 #define OPT_MCU_ESP32P4 907 ///< Espressif ESP32-P4 +#define OPT_MCU_ESP32C5 908 ///< Espressif ESP32-C5 +#define OPT_MCU_ESP32C61 909 ///< Espressif ESP32-C61 #define TUSB_MCU_VENDOR_ESPRESSIF (CFG_TUSB_MCU >= 900 && CFG_TUSB_MCU < 1000) // check if Espressif MCU #define TUP_MCU_ESPRESSIF TUSB_MCU_VENDOR_ESPRESSIF // for backward compatibility From e1cd4aa91f184f79e3c069968c9ee1f634daba3e Mon Sep 17 00:00:00 2001 From: ohmdelta <64962148+ohmdelta@users.noreply.github.com> Date: Wed, 20 Aug 2025 01:23:33 +0100 Subject: [PATCH 332/382] add some consumer page configs --- src/class/hid/hid.h | 393 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 388 insertions(+), 5 deletions(-) diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index c2434c20d..0fc0e1377 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -893,14 +893,51 @@ enum { /// HID Usage Table: Consumer Page (0x0C) /// Only contains controls that supported by Windows (whole list is too long) enum { + HID_USAGE_CONSUMER_UNASSIGNED = 0x0000, + // Generic Control HID_USAGE_CONSUMER_CONTROL = 0x0001, + HID_USAGE_CONSUMER_NUMERIC_KEY_PAD = 0x0002, + HID_USAGE_CONSUMER_PROGRAMMABLE_BUTTONS = 0x0003, + HID_USAGE_CONSUMER_MICROPHONE = 0x0004, + HID_USAGE_CONSUMER_HEADPHONE = 0x0005, + HID_USAGE_CONSUMER_GRAPHIC_EQUALIZER = 0x0006, + // 07-1F Reserved + + HID_USAGE_CONSUMER_PLUS_10 = 0x0020, + HID_USAGE_CONSUMER_PLUS_100 = 0x0021, + HID_USAGE_CONSUMER_AM_PM = 0x0022, + // 23-3F Reserved // Power Control HID_USAGE_CONSUMER_POWER = 0x0030, HID_USAGE_CONSUMER_RESET = 0x0031, HID_USAGE_CONSUMER_SLEEP = 0x0032, + HID_USAGE_CONSUMER_SLEEP_AFTER = 0x0033, + HID_USAGE_CONSUMER_SLEEP_MODE = 0x0034, + HID_USAGE_CONSUMER_ILLUMINATION = 0x0035, + HID_USAGE_CONSUMER_FUNCTION_BUTTONS = 0x0036, + // 37-3F Reserved + HID_USAGE_CONSUMER_MENU = 0x0040, + HID_USAGE_CONSUMER_MENU_PICK = 0x0041, + HID_USAGE_CONSUMER_MENU_UP = 0x0042, + HID_USAGE_CONSUMER_MENU_DOWN = 0x0043, + HID_USAGE_CONSUMER_MENU_LEFT = 0x0044, + HID_USAGE_CONSUMER_MENU_RIGHT = 0x0045, + HID_USAGE_CONSUMER_MENU_ESCAPE = 0x0046, + HID_USAGE_CONSUMER_MENU_VALUE_INCREASE = 0x0047, + HID_USAGE_CONSUMER_MENU_VALUE_DECREASE = 0x0048, + // 49-5F Reserved + HID_USAGE_CONSUMER_DATA_ON_SCREEN = 0x0060, + HID_USAGE_CONSUMER_CLOSED_CAPTION = 0x0061, + HID_USAGE_CONSUMER_CLOSED_CAPTION_SELECT = 0x0062, + HID_USAGE_CONSUMER_VCR_TV = 0x0063, + HID_USAGE_CONSUMER_BROADCAST_MODE = 0x0064, + HID_USAGE_CONSUMER_SNAPSHOT = 0x0065, + HID_USAGE_CONSUMER_STILL = 0x0066, + + // 67-7F Reserved // Screen Brightness HID_USAGE_CONSUMER_BRIGHTNESS_INCREMENT = 0x006F, HID_USAGE_CONSUMER_BRIGHTNESS_DECREMENT = 0x0070, @@ -912,40 +949,386 @@ enum { HID_USAGE_CONSUMER_WIRELESS_RADIO_LED = 0x00C7, HID_USAGE_CONSUMER_WIRELESS_RADIO_SLIDER_SWITCH = 0x00C8, - // Media Control - HID_USAGE_CONSUMER_PLAY_PAUSE = 0x00CD, + HID_USAGE_CONSUMER_SELECTION = 0x0080, + HID_USAGE_CONSUMER_ASSIGN_SELECTION = 0x0081, + HID_USAGE_CONSUMER_MODE_STEP = 0x0082, + HID_USAGE_CONSUMER_RECALL_LAST = 0x0083, + HID_USAGE_CONSUMER_ENTER_CHANNEL = 0x0084, + HID_USAGE_CONSUMER_ORDER_MOVIE = 0x0085, + HID_USAGE_CONSUMER_CHANNEL = 0x0086, + HID_USAGE_CONSUMER_MEDIA_SELECTION = 0x0087, + HID_USAGE_CONSUMER_MEDIA_SELECT_COMPUTER = 0x0088, + HID_USAGE_CONSUMER_MEDIA_SELECT_TV = 0x0089, + HID_USAGE_CONSUMER_MEDIA_SELECT_WWW = 0x008A, + HID_USAGE_CONSUMER_MEDIA_SELECT_DVD = 0x008B, + HID_USAGE_CONSUMER_MEDIA_SELECT_TELEPHONE = 0x008C, + HID_USAGE_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE = 0x008D, + HID_USAGE_CONSUMER_MEDIA_SELECT_VIDEO_PHONE = 0x008E, + HID_USAGE_CONSUMER_MEDIA_SELECT_GAMES = 0x008F, + HID_USAGE_CONSUMER_MEDIA_SELECT_MESSAGES = 0x0090, + HID_USAGE_CONSUMER_MEDIA_SELECT_CD = 0x0091, + HID_USAGE_CONSUMER_MEDIA_SELECT_VCR = 0x0092, + HID_USAGE_CONSUMER_MEDIA_SELECT_TUNER = 0x0093, + HID_USAGE_CONSUMER_QUIT = 0x0094, + HID_USAGE_CONSUMER_HELP = 0x0095, + HID_USAGE_CONSUMER_MEDIA_SELECT_TAPE = 0x0096, + HID_USAGE_CONSUMER_MEDIA_SELECT_CABLE = 0x0097, + HID_USAGE_CONSUMER_MEDIA_SELECT_SATELLITE = 0x0098, + HID_USAGE_CONSUMER_MEDIA_SELECT_SECURITY = 0x0099, + HID_USAGE_CONSUMER_MEDIA_SELECT_HOME = 0x009A, + HID_USAGE_CONSUMER_MEDIA_SELECT_CALL = 0x009B, + HID_USAGE_CONSUMER_CHANNEL_INCREMENT = 0x009C, + HID_USAGE_CONSUMER_CHANNEL_DECREMENT = 0x009D, + HID_USAGE_CONSUMER_MEDIA_SELECT_SAP = 0x009E, + // 9F Reserved + HID_USAGE_CONSUMER_VCR_PLUS = 0x00A0, + HID_USAGE_CONSUMER_ONCE = 0x00A1, + HID_USAGE_CONSUMER_DAILY = 0x00A2, + HID_USAGE_CONSUMER_WEEKLY = 0x00A3, + HID_USAGE_CONSUMER_MONTHLY = 0x00A4, + // A5-AF Reserved + + HID_USAGE_CONSUMER_PLAY = 0x00B0, + HID_USAGE_CONSUMER_PAUSE = 0x00B1, + HID_USAGE_CONSUMER_RECORD = 0x00B2, + HID_USAGE_CONSUMER_FAST_FORWARD = 0x00B3, + HID_USAGE_CONSUMER_REWIND = 0x00B4, + HID_USAGE_CONSUMER_SCAN_NEXT_TRACK = 0x00B5, HID_USAGE_CONSUMER_SCAN_NEXT = 0x00B5, + HID_USAGE_CONSUMER_SCAN_PREVIOUS_TRACK = 0x00B6, HID_USAGE_CONSUMER_SCAN_PREVIOUS = 0x00B6, HID_USAGE_CONSUMER_STOP = 0x00B7, + HID_USAGE_CONSUMER_EJECT = 0x00B8, + HID_USAGE_CONSUMER_RANDOM_PLAY = 0x00B9, + HID_USAGE_CONSUMER_SELECT_DISC = 0x00BA, + HID_USAGE_CONSUMER_ENTER_DISC = 0x00BB, + HID_USAGE_CONSUMER_REPEAT = 0x00BC, + HID_USAGE_CONSUMER_TRACKING = 0x00BD, + HID_USAGE_CONSUMER_TRACK_NORMAL = 0x00BE, + HID_USAGE_CONSUMER_SLOW_TRACKING = 0x00BF, + HID_USAGE_CONSUMER_FRAME_FORWARD = 0x00C0, + HID_USAGE_CONSUMER_FRAME_BACK = 0x00C1, + HID_USAGE_CONSUMER_MARK = 0x00C2, + HID_USAGE_CONSUMER_CLEAR_MARK = 0x00C3, + HID_USAGE_CONSUMER_REPEAT_FROM_MARK = 0x00C4, + HID_USAGE_CONSUMER_RETURN_TO_MARK = 0x00C5, + HID_USAGE_CONSUMER_SEARCH_MARK_FORWARD = 0x00C6, + HID_USAGE_CONSUMER_SEARCH_MARK_BACKWARDS = 0x00C7, + HID_USAGE_CONSUMER_COUNTER_RESET = 0x00C8, + HID_USAGE_CONSUMER_SHOW_COUNTER = 0x00C9, + HID_USAGE_CONSUMER_TRACKING_INCREMENT = 0x00CA, + HID_USAGE_CONSUMER_TRACKING_DECREMENT = 0x00CB, + HID_USAGE_CONSUMER_STOP_EJECT = 0x00CC, + + + // Media Control + HID_USAGE_CONSUMER_PLAY_PAUSE = 0x00CD, + + HID_USAGE_CONSUMER_PLAY_SKIP = 0x00CE, + + // CF-DF Reserved HID_USAGE_CONSUMER_VOLUME = 0x00E0, + HID_USAGE_CONSUMER_BALANCE = 0x00E1, HID_USAGE_CONSUMER_MUTE = 0x00E2, HID_USAGE_CONSUMER_BASS = 0x00E3, HID_USAGE_CONSUMER_TREBLE = 0x00E4, HID_USAGE_CONSUMER_BASS_BOOST = 0x00E5, + HID_USAGE_CONSUMER_SURROUND_MODE = 0x00E6, + HID_USAGE_CONSUMER_LOUDNESS = 0x00E7, + HID_USAGE_CONSUMER_MPX = 0x00E8, HID_USAGE_CONSUMER_VOLUME_INCREMENT = 0x00E9, HID_USAGE_CONSUMER_VOLUME_DECREMENT = 0x00EA, + // EB-EF Reserved + HID_USAGE_CONSUMER_SPEED_SELECT = 0x00F0, + HID_USAGE_CONSUMER_PLAYBACK_SPEED = 0x00F1, + HID_USAGE_CONSUMER_STANDARD_PLAY = 0x00F2, + HID_USAGE_CONSUMER_LONG_PLAY = 0x00F3, + HID_USAGE_CONSUMER_EXTENDED_PLAY = 0x00F4, + HID_USAGE_CONSUMER_SLOW = 0x00F5, + // F6-FF Reserved + HID_USAGE_CONSUMER_FAN_ENABLE = 0x0100, + HID_USAGE_CONSUMER_FAN_SPEED = 0x0101, + HID_USAGE_CONSUMER_LIGHT_ENABLE = 0x0102, + HID_USAGE_CONSUMER_LIGHT_ILLUMINATION_LEVEL = 0x0103, + HID_USAGE_CONSUMER_CLIMATE_CONTROL_ENABLE = 0x0104, + HID_USAGE_CONSUMER_ROOM_TEMPERATURE = 0x0105, + HID_USAGE_CONSUMER_SECURITY_ENABLE = 0x0106, + HID_USAGE_CONSUMER_FIRE_ALARM = 0x0107, + HID_USAGE_CONSUMER_POLICE_ALARM = 0x0108, + HID_USAGE_CONSUMER_PROXIMITY = 0x0109, + HID_USAGE_CONSUMER_MOTION = 0x010A, + HID_USAGE_CONSUMER_DURESS_ALARM = 0x010B, + HID_USAGE_CONSUMER_HOLDUP_ALARM = 0x010C, + HID_USAGE_CONSUMER_MEDICAL_ALARM = 0x010D, + // 10E-14F Reserved + HID_USAGE_CONSUMER_BALANCE_RIGHT = 0x0150, + HID_USAGE_CONSUMER_BALANCE_LEFT = 0x0151, HID_USAGE_CONSUMER_BASS_INCREMENT = 0x0152, HID_USAGE_CONSUMER_BASS_DECREMENT = 0x0153, HID_USAGE_CONSUMER_TREBLE_INCREMENT = 0x0154, HID_USAGE_CONSUMER_TREBLE_DECREMENT = 0x0155, - // Application Launcher + // 156-15F Reserved + HID_USAGE_CONSUMER_SPEAKER_SYSTEM = 0x0160, + HID_USAGE_CONSUMER_CHANNEL_LEFT = 0x0161, + HID_USAGE_CONSUMER_CHANNEL_RIGHT = 0x0162, + HID_USAGE_CONSUMER_CHANNEL_CENTER = 0x0163, + HID_USAGE_CONSUMER_CHANNEL_FRONT = 0x0164, + HID_USAGE_CONSUMER_CHANNEL_CENTER_FRONT = 0x0165, + HID_USAGE_CONSUMER_CHANNEL_SIDE = 0x0166, + HID_USAGE_CONSUMER_CHANNEL_SURROUND = 0x0167, + HID_USAGE_CONSUMER_CHANNEL_LOW_FREQUENCY = 0x0168, + // Enhancement + // CL 15.12.1 + HID_USAGE_CONSUMER_CHANNEL_TOP = 0x0169, + HID_USAGE_CONSUMER_CHANNEL_UNKNOWN = 0x016A, + // 16B-16F Reserved + HID_USAGE_CONSUMER_SUB_CHANNEL = 0x0170, + HID_USAGE_CONSUMER_SUB_CHANNEL_INCREMENT = 0x0171, + HID_USAGE_CONSUMER_SUB_CHANNEL_DECREMENT = 0x0172, + HID_USAGE_CONSUMER_ALTERNATE_AUDIO_INCREMENT = 0x0173, + HID_USAGE_CONSUMER_ALTERNATE_AUDIO_DECREMENT = 0x0174, + // 175-17F Reserved + HID_USAGE_CONSUMER_APPLICATION_LAUNCH_BUTTONS = 0x0180, + HID_USAGE_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION = 0x0181, + // Tool + // Sel 15.15 + HID_USAGE_CONSUMER_AL_PROGRAMMABLE_BUTTON = 0x0182, + // Configuration + // Sel 15.15 HID_USAGE_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x0183, + HID_USAGE_CONSUMER_AL_CONSUMER_CONTROL = 0x0183, + // Configuration + // Sel 15.15 + HID_USAGE_CONSUMER_AL_WORD_PROCESSOR = 0x0184, + HID_USAGE_CONSUMER_AL_TEXT_EDITOR = 0x0185, + HID_USAGE_CONSUMER_AL_SPREADSHEET = 0x0186, + HID_USAGE_CONSUMER_AL_GRAPHICS_EDITOR = 0x0187, + HID_USAGE_CONSUMER_AL_PRESENTATION_APP = 0x0188, + HID_USAGE_CONSUMER_AL_DATABASE_APP = 0x0189, HID_USAGE_CONSUMER_AL_EMAIL_READER = 0x018A, + HID_USAGE_CONSUMER_AL_NEWSREADER = 0x018B, + HID_USAGE_CONSUMER_AL_VOICEMAIL = 0x018C, + HID_USAGE_CONSUMER_AL_CONTACTS_ADDRESS_BOOK = 0x018D, + HID_USAGE_CONSUMER_AL_CALENDAR_SCHEDULE = 0x018E, + HID_USAGE_CONSUMER_AL_TASK_PROJECT_MANAGER = 0x018F, + HID_USAGE_CONSUMER_AL_LOG_JOURNAL_TIMECARD = 0x0190, + HID_USAGE_CONSUMER_AL_CHECKBOOK_FINANCE = 0x0191, HID_USAGE_CONSUMER_AL_CALCULATOR = 0x0192, + HID_USAGE_CONSUMER_AL_A_V_CAPTURE_PLAYBACK = 0x0193, + HID_USAGE_CONSUMER_AL_LOCAL_MACHINE_BROWSER = 0x0194, HID_USAGE_CONSUMER_AL_LOCAL_BROWSER = 0x0194, - + HID_USAGE_CONSUMER_AL_LAN_WAN_BROWSER = 0x0195, + HID_USAGE_CONSUMER_AL_INTERNET_BROWSER = 0x0196, + HID_USAGE_CONSUMER_AL_REMOTE_NETWORKING_ISP = 0x0197, + // Connect + // Sel 15.15 + HID_USAGE_CONSUMER_AL_NETWORK_CONFERENCE = 0x0198, + HID_USAGE_CONSUMER_AL_NETWORK_CHAT = 0x0199, + HID_USAGE_CONSUMER_AL_TELEPHONY_DIALER = 0x019A, + HID_USAGE_CONSUMER_AL_LOGON = 0x019B, + HID_USAGE_CONSUMER_AL_LOGOFF = 0x019C, + HID_USAGE_CONSUMER_AL_LOGON_LOGOFF = 0x019D, + HID_USAGE_CONSUMER_AL_TERMINAL_LOCK_SCREENSAVER = 0x019E, + HID_USAGE_CONSUMER_AL_CONTROL_PANEL = 0x019F, + HID_USAGE_CONSUMER_AL_COMMAND_LINE_PROCESSOR_RUN = 0x01A0, + HID_USAGE_CONSUMER_AL_PROCESS_TASK_MANAGER = 0x01A1, + HID_USAGE_CONSUMER_AL_SELECT_TASK_APPLICATION = 0x01A2, + HID_USAGE_CONSUMER_AL_NEXT_TASK_APPLICATION = 0x01A3, + HID_USAGE_CONSUMER_AL_PREVIOUS_TASK_APPLICATION = 0x01A4, + HID_USAGE_CONSUMER_AL_PREEMPTIVE_HALT = 0x01A5, + // Task_Application + // Sel 15.15 + HID_USAGE_CONSUMER_AL_INTEGRATED_HELP_CENTER = 0x01A6, + HID_USAGE_CONSUMER_AL_DOCUMENTS = 0x01A7, + HID_USAGE_CONSUMER_AL_THESAURUS = 0x01A8, + HID_USAGE_CONSUMER_AL_DICTIONARY = 0x01A9, + HID_USAGE_CONSUMER_AL_DESKTOP = 0x01AA, + HID_USAGE_CONSUMER_AL_SPELL_CHECK = 0x01AB, + HID_USAGE_CONSUMER_AL_GRAMMAR_CHECK = 0x01AC, + HID_USAGE_CONSUMER_AL_WIRELESS_STATUS = 0x01AD, + HID_USAGE_CONSUMER_AL_KEYBOARD_LAYOUT = 0x01AE, + HID_USAGE_CONSUMER_AL_VIRUS_PROTECTION = 0x01AF, + HID_USAGE_CONSUMER_AL_ENCRYPTION = 0x01B0, + HID_USAGE_CONSUMER_AL_SCREEN_SAVER = 0x01B1, + HID_USAGE_CONSUMER_AL_ALARMS = 0x01B2, + HID_USAGE_CONSUMER_AL_CLOCK = 0x01B3, + HID_USAGE_CONSUMER_AL_FILE_BROWSER = 0x01B4, + HID_USAGE_CONSUMER_AL_POWER_STATUS = 0x01B5, + HID_USAGE_CONSUMER_AL_IMAGE_BROWSER = 0x01B6, + HID_USAGE_CONSUMER_AL_AUDIO_BROWSER = 0x01B7, + HID_USAGE_CONSUMER_AL_MOVIE_BROWSER = 0x01B8, + HID_USAGE_CONSUMER_AL_DIGITAL_RIGHTS_MANAGER = 0x01B9, + HID_USAGE_CONSUMER_AL_DIGITAL_WALLET = 0x01BA, + // 1BB Reserved + HID_USAGE_CONSUMER_AL_INSTANT_MESSAGING = 0x01BC, + HID_USAGE_CONSUMER_AL_OEM_FEATURES_TIPS_TUTORIAL = 0x01BD, + // Browser + // Sel 15.15 + HID_USAGE_CONSUMER_AL_OEM_HELP = 0x01BE, + HID_USAGE_CONSUMER_AL_ONLINE_COMMUNITY = 0x01BF, + HID_USAGE_CONSUMER_AL_ENTERTAINMENT_CONTENT = 0x01C0, + // Browser + // Sel 15.15 + HID_USAGE_CONSUMER_AL_ONLINE_SHOPPING_BROWSER = 0x01C1, + HID_USAGE_CONSUMER_AL_SMARTCARD_INFORMATION_HELP = 0x01C2, + HID_USAGE_CONSUMER_AL_MARKET_MONITOR_FINANCE = 0x01C3, + // Browser + // Sel 15.15 + HID_USAGE_CONSUMER_AL_CUSTOMIZED_CORPORATE_NEWS = 0x01C4, + // Browser + // Sel 15.15 + HID_USAGE_CONSUMER_AL_ONLINE_ACTIVITY_BROWSER = 0x01C5, + HID_USAGE_CONSUMER_AL_RESEARCH_SEARCH_BROWSER = 0x01C6, + HID_USAGE_CONSUMER_AL_AUDIO_PLAYER = 0x01C7, + // 1C8-1FF Reserved + HID_USAGE_CONSUMER_GENERIC_GUI_APPLICATION = 0x0200, + // ' Controls + // ' + HID_USAGE_CONSUMER_AC_NEW = 0x0201, + HID_USAGE_CONSUMER_AC_OPEN = 0x0202, + HID_USAGE_CONSUMER_AC_CLOSE = 0x0203, + HID_USAGE_CONSUMER_AC_EXIT = 0x0204, + HID_USAGE_CONSUMER_AC_MAXIMIZE = 0x0205, + HID_USAGE_CONSUMER_AC_MINIMIZE = 0x0206, + HID_USAGE_CONSUMER_AC_SAVE = 0x0207, + HID_USAGE_CONSUMER_AC_PRINT = 0x0208, + HID_USAGE_CONSUMER_AC_PROPERTIES = 0x0209, + HID_USAGE_CONSUMER_AC_UNDO = 0x021A, + HID_USAGE_CONSUMER_AC_COPY = 0x021B, + HID_USAGE_CONSUMER_AC_CUT = 0x021C, + HID_USAGE_CONSUMER_AC_PASTE = 0x021D, + HID_USAGE_CONSUMER_AC_SELECT_ALL = 0x021E, + HID_USAGE_CONSUMER_AC_FIND = 0x021F, + HID_USAGE_CONSUMER_AC_FIND_AND_REPLACE = 0x0220, // Browser/Explorer Specific HID_USAGE_CONSUMER_AC_SEARCH = 0x0221, + HID_USAGE_CONSUMER_AC_GO_TO = 0x0222, HID_USAGE_CONSUMER_AC_HOME = 0x0223, HID_USAGE_CONSUMER_AC_BACK = 0x0224, HID_USAGE_CONSUMER_AC_FORWARD = 0x0225, HID_USAGE_CONSUMER_AC_STOP = 0x0226, HID_USAGE_CONSUMER_AC_REFRESH = 0x0227, + HID_USAGE_CONSUMER_AC_PREVIOUS_LINK = 0x0228, + HID_USAGE_CONSUMER_AC_NEXT_LINK = 0x0229, HID_USAGE_CONSUMER_AC_BOOKMARKS = 0x022A, - + HID_USAGE_CONSUMER_AC_HISTORY = 0x022B, + HID_USAGE_CONSUMER_AC_SUBSCRIPTIONS = 0x022C, + HID_USAGE_CONSUMER_AC_ZOOM_IN = 0x022D, + HID_USAGE_CONSUMER_AC_ZOOM_OUT = 0x022E, + HID_USAGE_CONSUMER_AC_ZOOM = 0x022F, + HID_USAGE_CONSUMER_AC_FULL_SCREEN_VIEW = 0x0230, + HID_USAGE_CONSUMER_AC_NORMAL_VIEW = 0x0231, + HID_USAGE_CONSUMER_AC_VIEW_TOGGLE = 0x0232, + HID_USAGE_CONSUMER_AC_SCROLL_UP = 0x0233, + HID_USAGE_CONSUMER_AC_SCROLL_DOWN = 0x0234, + HID_USAGE_CONSUMER_AC_SCROLL = 0x0235, + HID_USAGE_CONSUMER_AC_PAN_LEFT = 0x0236, + HID_USAGE_CONSUMER_AC_PAN_RIGHT = 0x0237, // Mouse Horizontal scroll HID_USAGE_CONSUMER_AC_PAN = 0x0238, + HID_USAGE_CONSUMER_AC_NEW_WINDOW = 0x0239, + HID_USAGE_CONSUMER_AC_TILE_HORIZONTALLY = 0x023A, + HID_USAGE_CONSUMER_AC_TILE_VERTICALLY = 0x023B, + HID_USAGE_CONSUMER_AC_FORMAT = 0x023C, + HID_USAGE_CONSUMER_AC_EDIT = 0x023D, + HID_USAGE_CONSUMER_AC_BOLD = 0x023E, + HID_USAGE_CONSUMER_AC_ITALICS = 0x023F, + HID_USAGE_CONSUMER_AC_UNDERLINE = 0x0240, + HID_USAGE_CONSUMER_AC_STRIKETHROUGH = 0x0241, + HID_USAGE_CONSUMER_AC_SUBSCRIPT = 0x0242, + HID_USAGE_CONSUMER_AC_SUPERSCRIPT = 0x0243, + HID_USAGE_CONSUMER_AC_ALL_CAPS = 0x0244, + HID_USAGE_CONSUMER_AC_ROTATE = 0x0245, + HID_USAGE_CONSUMER_AC_RESIZE = 0x0246, + HID_USAGE_CONSUMER_AC_FLIP_HORIZONTAL = 0x0247, + HID_USAGE_CONSUMER_AC_FLIP_VERTICAL = 0x0248, + HID_USAGE_CONSUMER_AC_MIRROR_HORIZONTAL = 0x0249, + HID_USAGE_CONSUMER_AC_MIRROR_VERTICAL = 0x024A, + HID_USAGE_CONSUMER_AC_FONT_SELECT = 0x024B, + HID_USAGE_CONSUMER_AC_FONT_COLOR = 0x024C, + HID_USAGE_CONSUMER_AC_FONT_SIZE = 0x024D, + HID_USAGE_CONSUMER_AC_JUSTIFY_LEFT = 0x024E, + HID_USAGE_CONSUMER_AC_JUSTIFY_CENTER_H = 0x024F, + HID_USAGE_CONSUMER_AC_JUSTIFY_RIGHT = 0x0250, + HID_USAGE_CONSUMER_AC_JUSTIFY_BLOCK_H = 0x0251, + HID_USAGE_CONSUMER_AC_JUSTIFY_TOP = 0x0252, + HID_USAGE_CONSUMER_AC_JUSTIFY_CENTER_V = 0x0253, + HID_USAGE_CONSUMER_AC_JUSTIFY_BOTTOM = 0x0254, + HID_USAGE_CONSUMER_AC_JUSTIFY_BLOCK_V = 0x0255, + HID_USAGE_CONSUMER_AC_INDENT_DECREASE = 0x0256, + HID_USAGE_CONSUMER_AC_INDENT_INCREASE = 0x0257, + HID_USAGE_CONSUMER_AC_NUMBERED_LIST = 0x0258, + HID_USAGE_CONSUMER_AC_RESTART_NUMBERING = 0x0259, + HID_USAGE_CONSUMER_AC_BULLETED_LIST = 0x025A, + HID_USAGE_CONSUMER_AC_PROMOTE = 0x025B, + HID_USAGE_CONSUMER_AC_DEMOTE = 0x025C, + HID_USAGE_CONSUMER_AC_YES = 0x025D, + HID_USAGE_CONSUMER_AC_NO = 0x025E, + HID_USAGE_CONSUMER_AC_CANCEL = 0x025F, + HID_USAGE_CONSUMER_AC_CATALOG = 0x0260, + HID_USAGE_CONSUMER_AC_BUY_CHECKOUT = 0x0261, + HID_USAGE_CONSUMER_AC_ADD_TO_CART = 0x0262, + HID_USAGE_CONSUMER_AC_EXPAND = 0x0263, + HID_USAGE_CONSUMER_AC_EXPAND_ALL = 0x0264, + HID_USAGE_CONSUMER_AC_COLLAPSE = 0x0265, + HID_USAGE_CONSUMER_AC_COLLAPSE_ALL = 0x0266, + HID_USAGE_CONSUMER_AC_PRINT_PREVIEW = 0x0267, + HID_USAGE_CONSUMER_AC_PASTE_SPECIAL = 0x0268, + HID_USAGE_CONSUMER_AC_INSERT_MODE = 0x0269, + HID_USAGE_CONSUMER_AC_DELETE = 0x026A, + HID_USAGE_CONSUMER_AC_LOCK = 0x026B, + HID_USAGE_CONSUMER_AC_UNLOCK = 0x026C, + HID_USAGE_CONSUMER_AC_PROTECT = 0x026D, + HID_USAGE_CONSUMER_AC_UNPROTECT = 0x026E, + HID_USAGE_CONSUMER_AC_ATTACH_COMMENT = 0x026F, + HID_USAGE_CONSUMER_AC_DELETE_COMMENT = 0x0270, + HID_USAGE_CONSUMER_AC_VIEW_COMMENT = 0x0271, + HID_USAGE_CONSUMER_AC_SELECT_WORD = 0x0272, + HID_USAGE_CONSUMER_AC_SELECT_SENTENCE = 0x0273, + HID_USAGE_CONSUMER_AC_SELECT_PARAGRAPH = 0x0274, + HID_USAGE_CONSUMER_AC_SELECT_COLUMN = 0x0275, + HID_USAGE_CONSUMER_AC_SELECT_ROW = 0x0276, + HID_USAGE_CONSUMER_AC_SELECT_TABLE = 0x0277, + HID_USAGE_CONSUMER_AC_SELECT_OBJECT = 0x0278, + HID_USAGE_CONSUMER_AC_REDO_REPEAT = 0x0279, + HID_USAGE_CONSUMER_AC_SORT = 0x027A, + HID_USAGE_CONSUMER_AC_SORT_ASCENDING = 0x027B, + HID_USAGE_CONSUMER_AC_SORT_DESCENDING = 0x027C, + HID_USAGE_CONSUMER_AC_FILTER = 0x027D, + HID_USAGE_CONSUMER_AC_SET_CLOCK = 0x027E, + HID_USAGE_CONSUMER_AC_VIEW_CLOCK = 0x027F, + HID_USAGE_CONSUMER_AC_SELECT_TIME_ZONE = 0x0280, + HID_USAGE_CONSUMER_AC_EDIT_TIME_ZONES = 0x0281, + HID_USAGE_CONSUMER_AC_SET_ALARM = 0x0282, + HID_USAGE_CONSUMER_AC_CLEAR_ALARM = 0x0283, + HID_USAGE_CONSUMER_AC_SNOOZE_ALARM = 0x0284, + HID_USAGE_CONSUMER_AC_RESET_ALARM = 0x0285, + HID_USAGE_CONSUMER_AC_SYNCHRONIZE = 0x0286, + HID_USAGE_CONSUMER_AC_SEND_RECEIVE = 0x0287, + HID_USAGE_CONSUMER_AC_SEND_TO = 0x0288, + HID_USAGE_CONSUMER_AC_REPLY = 0x0289, + HID_USAGE_CONSUMER_AC_REPLY_ALL = 0x028A, + HID_USAGE_CONSUMER_AC_FORWARD_MSG = 0x028B, + HID_USAGE_CONSUMER_AC_SEND = 0x028C, + HID_USAGE_CONSUMER_AC_ATTACH_FILE = 0x028D, + HID_USAGE_CONSUMER_AC_UPLOAD = 0x028E, + HID_USAGE_CONSUMER_AC_DOWNLOAD_SAVE_TARGET_AS = 0x028F, + HID_USAGE_CONSUMER_AC_SET_BORDERS = 0x0290, + HID_USAGE_CONSUMER_AC_INSERT_ROW = 0x0291, + HID_USAGE_CONSUMER_AC_INSERT_COLUMN = 0x0292, + HID_USAGE_CONSUMER_AC_INSERT_FILE = 0x0293, + HID_USAGE_CONSUMER_AC_INSERT_PICTURE = 0x0294, + HID_USAGE_CONSUMER_AC_INSERT_OBJECT = 0x0295, + HID_USAGE_CONSUMER_AC_INSERT_SYMBOL = 0x0296, + HID_USAGE_CONSUMER_AC_SAVE_AND_CLOSE = 0x0297, + HID_USAGE_CONSUMER_AC_RENAME = 0x0298, + HID_USAGE_CONSUMER_AC_MERGE = 0x0299, + HID_USAGE_CONSUMER_AC_SPLIT = 0x029A, + HID_USAGE_CONSUMER_AC_DISRIBUTE_HORIZONTALLY = 0x029B, + HID_USAGE_CONSUMER_AC_DISTRIBUTE_VERTICALLY = 0x029C, + // 29D-FFFF Reserved + }; /// HID Usage Table: Digitizer Page (0x0D) From bd9dd75da8718dfd56b2e91b658f81613ed1bf3a Mon Sep 17 00:00:00 2001 From: Mitsumine Suzu <60875431+verylowfreq@users.noreply.github.com> Date: Sun, 24 Aug 2025 16:26:08 +0900 Subject: [PATCH 333/382] Small cleanups. --- src/portable/wch/hcd_ch32_usbfs.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index d176f40c5..fc52597c2 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -120,9 +120,6 @@ static usb_edpt_t *get_empty_record_slot(void) { static usb_edpt_t *add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t max_packet_size, uint8_t xfer_type) { usb_edpt_t *slot = get_empty_record_slot(); - if (slot == NULL) { - PANIC("add_edpt_record(0x%02x, 0x%02x, ...) no slot for new record\r\n", dev_addr, ep_addr); - } TU_ASSERT(slot != NULL, NULL); slot->dev_addr = dev_addr; @@ -412,10 +409,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { } else { LOG_CH32_USBFSH("USB_PID_OUT continue...\r\n"); usb_current_xfer_info.buffer += tx_len; - uint16_t copylen = USBFS_TX_BUF_LEN; - if (copylen > usb_current_xfer_info.bufferlen) { - copylen = usb_current_xfer_info.bufferlen; - } + uint16_t copylen = TU_MIN(edpt_info->max_packet_size, usb_current_xfer_info.bufferlen); memcpy(USBFS_TX_Buf, usb_current_xfer_info.buffer, copylen); hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); return; @@ -445,7 +439,10 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { } } default: { - PANIC("Unknown PID: 0x%02x\n", request_pid); + LOG_CH32_USBFSH("hcd_int_handler() L%d: unexpected response PID: 0x%02x\r\n", __LINE__, response_pid); + usb_current_xfer_info.is_busy = false; + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + return; } } } else { @@ -474,7 +471,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); return; } else { - LOG_CH32_USBFSH("In USBHD_IRQHandler, unexpected response PID: 0x%02x\r\n", response_pid); + LOG_CH32_USBFSH("hcd_int_handler() L%d: unexpected response PID: 0x%02x\r\n", __LINE__, response_pid); usb_current_xfer_info.is_busy = false; hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); return; @@ -519,9 +516,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b usb_current_xfer_info.is_busy = true; usb_edpt_t *edpt_info = get_edpt_record(dev_addr, ep_addr); - if (edpt_info == NULL) { - PANIC("get_edpt_record() returned NULL in hcd_edpt_xfer()\r\n"); - } + TU_ASSERT(edpt_info != NULL); hardware_set_port_address_speed(dev_addr); @@ -537,10 +532,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b return hardware_start_xfer(USB_PID_IN, ep_addr, edpt_info->data_toggle); } else { LOG_CH32_USBFSH("hcd_edpt_xfer(): WRITE, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); - uint16_t copylen = USBFS_TX_BUF_LEN; - if (copylen > buflen) { - copylen = buflen; - } + uint16_t copylen = TU_MIN(edpt_info->max_packet_size, buflen); USBOTG_H_FS->HOST_TX_LEN = copylen; memcpy(USBFS_TX_Buf, buffer, copylen); return hardware_start_xfer(USB_PID_OUT, ep_addr, edpt_info->data_toggle); @@ -596,7 +588,6 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) { (void) rhport; (void) dev_addr; LOG_CH32_USBFSH("hcd_edpt_clear_stall(rhport=%d, dev_addr=0x%02x, ep_addr=0x%02x)\r\n", rhport, dev_addr, ep_addr); - // PANIC("\r\install\r\n"); uint8_t edpt_num = tu_edpt_number(ep_addr); uint8_t setup_request_clear_stall[8] = { 0x02, 0x01, 0x00, 0x00, edpt_num, 0x00, 0x00, 0x00 From 522a34ee28bcee6674ccd91973cb87869be98909 Mon Sep 17 00:00:00 2001 From: Mitsumine Suzu <60875431+verylowfreq@users.noreply.github.com> Date: Sun, 24 Aug 2025 16:28:32 +0900 Subject: [PATCH 334/382] Insert small delay for LowSpeed device --- src/portable/wch/hcd_ch32_usbfs.c | 35 +++++++++++++++++-------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index fc52597c2..38bb0ed59 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -55,18 +55,18 @@ TU_ATTR_ALIGNED(4) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN]; #define LOG_CH32_USBFSH(...) TU_LOG3(__VA_ARGS__) // Busywait for delay microseconds/nanoseconds -// static void loopdelay(uint32_t count) -// { -// volatile uint32_t c = count / 3; -// if (c == 0) { return; } -// // while (c-- != 0); -// asm volatile( -// "1: \n" // loop label -// " addi %0, %0, -1 \n" // c-- -// " bne %0, zero, 1b \n" // if (c != 0) goto loop -// : "+r"(c) // c is input/output operand -// ); -// } +static void loopdelay(uint32_t count) +{ + volatile uint32_t c = count / 3; + if (c == 0) { return; } + // while (c-- != 0); + asm volatile( + "1: \n" // loop label + " addi %0, %0, -1 \n" // c-- + " bne %0, zero, 1b \n" // if (c != 0) goto loop + : "+r"(c) // c is input/output operand + ); +} // Endpoint status @@ -194,10 +194,13 @@ static bool hardware_start_xfer(uint8_t pid, uint8_t ep_addr, uint8_t data_toggl : "(other)", pid, ep_addr, data_toggle); - // if (pid == USB_PID_IN) - // { // FIXME: long delay needed (at release build) about 30msec - // loopdelay(SystemCoreClock / 1000 * 30); - // } + //WORKAROUND: For LowSpeed device, insert small delay + bool is_lowspeed_device = tuh_speed_get(usb_current_xfer_info.dev_addr) == TUSB_SPEED_LOW; + if (is_lowspeed_device) { + //NOTE: worked -> SystemCoreClock / 1000000 * 50, 25 + // NOT worked -> 20 and less (at 144MHz internal clock) + loopdelay(SystemCoreClock / 1000000 * 40); + } uint8_t pid_edpt = (pid << 4) | (tu_edpt_number(ep_addr) & 0x0f); USBOTG_H_FS->HOST_TX_CTRL = (data_toggle != 0) ? USBFS_UH_T_TOG : 0; From a3bb7a90b3478f43d448443140b68c3473331f93 Mon Sep 17 00:00:00 2001 From: Mitsumine Suzu <60875431+verylowfreq@users.noreply.github.com> Date: Sun, 24 Aug 2025 16:46:12 +0900 Subject: [PATCH 335/382] Improve retry operation at NAK response. --- src/portable/wch/hcd_ch32_usbfs.c | 76 +++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 10 deletions(-) diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index 38bb0ed59..449908658 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -28,6 +28,8 @@ #if CFG_TUH_ENABLED && defined(TUP_USBIP_WCH_USBFS) && defined(CFG_TUH_WCH_USBIP_USBFS) && CFG_TUH_WCH_USBIP_USBFS +#include + #include "host/hcd.h" #include "host/usbh.h" #include "host/usbh_pvt.h" @@ -95,6 +97,7 @@ typedef struct usb_current_xfer_st { uint8_t *buffer; uint16_t bufferlen; uint16_t xferred_len; + bool nak_pending; } usb_current_xfer_t; static volatile usb_current_xfer_t usb_current_xfer_info = {}; @@ -351,6 +354,34 @@ void hcd_int_disable(uint8_t rhport) { interrupt_enabled = false; } +typedef struct { + uint8_t rhport; + uint8_t dev_addr; + uint8_t ep_addr; + uint16_t buflen; + uint8_t* buf; +} xfer_retry_param_t; + +static void xfer_retry(void* _params) { + LOG_CH32_USBFSH("xfer_retry()\r\n"); + xfer_retry_param_t* params = (xfer_retry_param_t*)_params; + if (usb_current_xfer_info.nak_pending) { + usb_current_xfer_info.nak_pending = false; + + uint8_t dev_addr = params->dev_addr; + uint8_t ep_addr = params->ep_addr; + uint16_t buflen = params->buflen; + uint8_t* buf = params->buf; + free(params); + + usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr); + if (edpt_info) { + hcd_edpt_xfer(0, dev_addr, ep_addr, buf, buflen); + } + } +} + + void hcd_int_handler(uint8_t rhport, bool in_isr) { (void) rhport; (void) in_isr; @@ -407,7 +438,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { if (usb_current_xfer_info.bufferlen == 0) { LOG_CH32_USBFSH("USB_PID_%s completed %d bytes\r\n", request_pid == USB_PID_OUT ? "OUT" : "SETUP", usb_current_xfer_info.xferred_len); usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, usb_current_xfer_info.xferred_len, XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(dev_addr, ep_addr, usb_current_xfer_info.xferred_len, XFER_RESULT_SUCCESS, in_isr); return; } else { LOG_CH32_USBFSH("USB_PID_OUT continue...\r\n"); @@ -432,7 +463,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { // USB device sent all data. LOG_CH32_USBFSH("USB_PID_IN completed\r\n"); usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, XFER_RESULT_SUCCESS, true); + hcd_event_xfer_complete(dev_addr, ep_addr, xferred_len, XFER_RESULT_SUCCESS, in_isr); return; } else { // USB device may send more data. @@ -444,7 +475,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { default: { LOG_CH32_USBFSH("hcd_int_handler() L%d: unexpected response PID: 0x%02x\r\n", __LINE__, response_pid); usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); return; } } @@ -458,25 +489,46 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { } else if (response_pid == USB_PID_NAK) { LOG_CH32_USBFSH("NAK reposense\r\n"); uint32_t elapsed_time = board_millis() - usb_current_xfer_info.start_ms; + (void)elapsed_time; if (edpt_info->xfer_type == TUSB_XFER_INTERRUPT) { usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, true); - } else if (elapsed_time > USB_XFER_TIMEOUT_MILLIS) { - usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_SUCCESS, in_isr); + } else { - hardware_start_xfer(request_pid, ep_addr, edpt_info->data_toggle); + usb_current_xfer_info.is_busy = false; + usb_current_xfer_info.nak_pending = true; + + xfer_retry_param_t* param_buf = malloc(sizeof(xfer_retry_param_t)); + xfer_retry_param_t param = { + .rhport = 0, + .dev_addr = dev_addr, + .ep_addr = ep_addr, + .buflen = usb_current_xfer_info.bufferlen, + .buf = usb_current_xfer_info.buffer + }; + memcpy(param_buf, ¶m, sizeof(xfer_retry_param_t)); + + hcd_event_t event = { + .rhport = rhport, + .dev_addr = dev_addr, + .event_id = USBH_EVENT_FUNC_CALL, + .func_call = { + .func = xfer_retry, + .param = param_buf + } + }; + hcd_event_handler(&event, in_isr); } return; } else if (response_pid == USB_PID_DATA0 || response_pid == USB_PID_DATA1) { LOG_CH32_USBFSH("Data toggle mismatched and DATA0/1 (not STALL). RX_LEN=%d\r\n", USBOTG_H_FS->RX_LEN); usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); return; } else { LOG_CH32_USBFSH("hcd_int_handler() L%d: unexpected response PID: 0x%02x\r\n", __LINE__, response_pid); usb_current_xfer_info.is_busy = false; - hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, true); + hcd_event_xfer_complete(dev_addr, ep_addr, 0, XFER_RESULT_FAILED, in_isr); return; } } @@ -495,6 +547,8 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const uint8_t xfer_type = ep_desc->bmAttributes.xfer; LOG_CH32_USBFSH("hcd_edpt_open(rhport=%d, dev_addr=0x%02x, %p) EndpointAdderss=0x%02x,maxPacketSize=%d,xfer_type=%d\r\n", rhport, dev_addr, ep_desc, ep_addr, max_packet_size, xfer_type); + while (usb_current_xfer_info.is_busy) { } + if (ep_num == 0x00) { TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x00, max_packet_size, xfer_type) != NULL, false); TU_ASSERT(get_or_add_edpt_record(dev_addr, 0x80, max_packet_size, xfer_type) != NULL, false); @@ -529,6 +583,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b usb_current_xfer_info.bufferlen = buflen; usb_current_xfer_info.start_ms = board_millis(); usb_current_xfer_info.xferred_len = 0; + usb_current_xfer_info.nak_pending = false; if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { LOG_CH32_USBFSH("hcd_edpt_xfer(): READ, dev_addr=0x%02x, ep_addr=0x%02x, len=%d\r\n", dev_addr, ep_addr, buflen); @@ -581,6 +636,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet usb_current_xfer_info.buffer = USBFS_TX_Buf; usb_current_xfer_info.bufferlen = setup_packet_datalen; usb_current_xfer_info.xferred_len = 0; + usb_current_xfer_info.nak_pending = false; hardware_start_xfer(USB_PID_SETUP, 0, 0); From a6b4ed91656c0d2ec54c72a00e993b8ad0bb9dc6 Mon Sep 17 00:00:00 2001 From: Aleksei Musin Date: Sun, 24 Aug 2025 17:13:09 +0400 Subject: [PATCH 336/382] STM32N6570-DK board is added. Build with DEBUG=1 (make BOARD=stm32n6570dk DEBUG=1 all), otherwise it does not work for now. Tested with examples/device/cdc_dual_ports --- .../stm32n6570dk/STM32N657XX_AXISRAM2_fsbl.ld | 203 +++++++++++++ .../stm32n6/boards/stm32n6570dk/board.cmake | 17 ++ hw/bsp/stm32n6/boards/stm32n6570dk/board.h | 283 ++++++++++++++++++ hw/bsp/stm32n6/boards/stm32n6570dk/board.mk | 17 ++ 4 files changed, 520 insertions(+) create mode 100644 hw/bsp/stm32n6/boards/stm32n6570dk/STM32N657XX_AXISRAM2_fsbl.ld create mode 100644 hw/bsp/stm32n6/boards/stm32n6570dk/board.cmake create mode 100644 hw/bsp/stm32n6/boards/stm32n6570dk/board.h create mode 100644 hw/bsp/stm32n6/boards/stm32n6570dk/board.mk diff --git a/hw/bsp/stm32n6/boards/stm32n6570dk/STM32N657XX_AXISRAM2_fsbl.ld b/hw/bsp/stm32n6/boards/stm32n6570dk/STM32N657XX_AXISRAM2_fsbl.ld new file mode 100644 index 000000000..e4c792cd8 --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n6570dk/STM32N657XX_AXISRAM2_fsbl.ld @@ -0,0 +1,203 @@ +/* +****************************************************************************** +** +** @file : STM32N657XX_AXISRAM2_fsbl.ld +** +** @author : GPM Application Team +** +** @brief : Linker script for STM32N657XX Device from STM32N6 series +** 512 KBytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +****************************************************************************** +** @attention +** +** Copyright (c) 2023 STMicroelectronics. +** All rights reserved. +** +** This software is licensed under terms that can be found in the LICENSE file +** in the root directory of this software component. +** If no LICENSE file comes with this software, it is provided AS-IS. +** +****************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ +_sstack = _estack - _Min_Stack_Size; + +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x800; /* required amount of stack */ + +/* Memories definition */ +MEMORY +{ + ROM (xrw) : ORIGIN = 0x34180400, LENGTH = 255K + RAM (xrw) : ORIGIN = 0x341C0000, LENGTH = 256K +} + +/* Sections */ +SECTIONS +{ + /* The startup code into "RAM" Ram type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >ROM + + /* The program code and other data into "RAM" Ram type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >ROM + + /* Constant data into "RAM" Ram type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >ROM + + .ARM.extab (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >ROM + + .ARM (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >ROM + + .preinit_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >ROM + + .init_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >ROM + + .fini_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >ROM + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> ROM + + .noncacheable : + { + . = ALIGN(8); + __snoncacheable = .;/* create symbol for start of section */ + KEEP(*(.noncacheable)) + . = ALIGN(8); + __enoncacheable = .; /* create symbol for end of section */ + } > RAM + + + .gnu.sgstubs : + { + . = ALIGN(4); + *(.gnu.sgstubs*) /* Secure Gateway stubs */ + . = ALIGN(4); + } >ROM + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/hw/bsp/stm32n6/boards/stm32n6570dk/board.cmake b/hw/bsp/stm32n6/boards/stm32n6570dk/board.cmake new file mode 100644 index 000000000..e88efefb9 --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n6570dk/board.cmake @@ -0,0 +1,17 @@ +set(MCU_VARIANT stm32n657xx) +set(JLINK_DEVICE stm32n6xx) + +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/STM32N657XX_AXISRAM2_fsbl.ld) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC + STM32N657xx + ) + target_sources(${TARGET} PUBLIC + ${ST_TCPP0203}/tcpp0203.c + ${ST_TCPP0203}/tcpp0203_reg.c + ) + target_include_directories(${TARGET} PUBLIC + ${ST_TCPP0203} + ) +endfunction() diff --git a/hw/bsp/stm32n6/boards/stm32n6570dk/board.h b/hw/bsp/stm32n6/boards/stm32n6570dk/board.h new file mode 100644 index 000000000..96e430c7a --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n6570dk/board.h @@ -0,0 +1,283 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: STM32N6570-DK + url: https://www.st.com/en/evaluation-tools/stm32n6570-dk.html +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stm32n657xx.h" +#include "stm32n6xx_ll_exti.h" +#include "stm32n6xx_ll_system.h" +#include "tcpp0203.h" + +#define UART_DEV USART1 +#define UART_CLK_EN __HAL_RCC_USART1_CLK_ENABLE + +#define BOARD_TUD_RHPORT 1 + +// VBUS Sense detection +#define OTG_FS_VBUS_SENSE 1 +#define OTG_HS_VBUS_SENSE 1 + +#define PINID_LED 0 +#define PINID_BUTTON 1 +#define PINID_UART_TX 2 +#define PINID_UART_RX 3 +#define PINID_TCPP0203_EN 4 + +static board_pindef_t board_pindef[] = { + {// LED + .port = GPIOG, + .pin_init = {.Pin = GPIO_PIN_10, .Mode = GPIO_MODE_OUTPUT_PP, .Pull = GPIO_PULLDOWN, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0}, + .active_state = 1}, + {// Button + .port = GPIOC, + .pin_init = {.Pin = GPIO_PIN_13, .Mode = GPIO_MODE_INPUT, .Pull = GPIO_PULLDOWN, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0}, + .active_state = 1}, + {// UART TX + .port = GPIOE, + .pin_init = {.Pin = GPIO_PIN_5, .Mode = GPIO_MODE_AF_PP, .Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_LOW, .Alternate = GPIO_AF7_USART1}, + .active_state = 0}, + {// UART RX + .port = GPIOE, + .pin_init = {.Pin = GPIO_PIN_6, .Mode = GPIO_MODE_AF_PP, .Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_LOW, .Alternate = GPIO_AF7_USART1}, + .active_state = 0}, + {// VBUS input pin used for TCPP0203 EN + .port = GPIOA, + .pin_init = {.Pin = GPIO_PIN_4, .Mode = GPIO_MODE_OUTPUT_PP, .Pull = GPIO_PULLDOWN, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0}, + .active_state = 0}, + { + // I2C SCL for TCPP0203 + .port = GPIOD, + .pin_init = {.Pin = GPIO_PIN_14, .Mode = GPIO_MODE_AF_OD, .Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_LOW, .Alternate = GPIO_AF4_I2C2}, + }, + { + // I2C SDA for TCPP0203 + .port = GPIOD, + .pin_init = {.Pin = GPIO_PIN_4, .Mode = GPIO_MODE_AF_OD, .Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_LOW, .Alternate = GPIO_AF4_I2C2}, + }, + { + // INT for TCPP0203 + .port = GPIOD, + .pin_init = {.Pin = GPIO_PIN_10, .Mode = GPIO_MODE_IT_FALLING, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0}, + }, +}; + +//--------------------------------------------------------------------+ +// RCC Clock +//--------------------------------------------------------------------+ +void SystemClock_Config(void) { + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + /* Configure the power domain */ + if (HAL_PWREx_ConfigSupply(PWR_EXTERNAL_SOURCE_SUPPLY) != HAL_OK) { + Error_Handler(); + } + + /* Get current CPU/System buses clocks configuration */ + /* and if necessary switch to intermediate HSI clock */ + /* to ensure target clock can be set */ + HAL_RCC_GetClockConfig(&RCC_ClkInitStruct); + if ((RCC_ClkInitStruct.CPUCLKSource == RCC_CPUCLKSOURCE_IC1) || + (RCC_ClkInitStruct.SYSCLKSource == RCC_SYSCLKSOURCE_IC2_IC6_IC11)) { + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_CPUCLK | RCC_CLOCKTYPE_SYSCLK); + RCC_ClkInitStruct.CPUCLKSource = RCC_CPUCLKSOURCE_HSI; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct) != HAL_OK) { + Error_Handler(); + } + } + + /* HSE selected as source (stable clock on Level 0 samples */ + /* PLL1 output = ((HSE/PLLM)*PLLN)/PLLP1/PLLP2 */ + /* = ((48000000/3)*75)/1/1 */ + /* = (16000000*75)/1/1 */ + /* = 1200000000 (1200 MHz) */ + /* PLL2 off */ + /* PLL3 off */ + /* PLL4 off */ + + /* Enable HSE && HSI */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSIState = RCC_HSI_OFF; + RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; /* 48 MHz */ + + RCC_OscInitStruct.PLL1.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL1.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL1.PLLM = 3; + RCC_OscInitStruct.PLL1.PLLN = 75; /* PLL1 VCO = 48/3 * 75 = 1200MHz */ + RCC_OscInitStruct.PLL1.PLLP1 = 1; /* PLL output = PLL VCO frequency / (PLLP1 * PLLP2) */ + RCC_OscInitStruct.PLL1.PLLP2 = 1; /* PLL output = 1200 MHz */ + RCC_OscInitStruct.PLL1.PLLFractional = 0; + + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + /* Initialization error */ + Error_Handler(); + } + + /* Select PLL1 outputs as CPU and System bus clock source */ + /* CPUCLK = ic1_ck = PLL1 output/ic1_divider = 600 MHz */ + /* SYSCLK = ic2_ck = PLL1 output/ic2_divider = 400 MHz */ + /* Configure the HCLK clock divider */ + /* HCLK = PLL1 SYSCLK/HCLK divider = 200 MHz */ + /* PCLKx = HCLK / PCLKx divider = 200 MHz */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_CPUCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | + RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK4 | RCC_CLOCKTYPE_PCLK5); + RCC_ClkInitStruct.CPUCLKSource = RCC_CPUCLKSOURCE_IC1; + RCC_ClkInitStruct.IC1Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1; + RCC_ClkInitStruct.IC1Selection.ClockDivider = 2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_IC2_IC6_IC11; + RCC_ClkInitStruct.IC2Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1; + RCC_ClkInitStruct.IC2Selection.ClockDivider = 3; + RCC_ClkInitStruct.IC6Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1; + RCC_ClkInitStruct.IC6Selection.ClockDivider = 3; + RCC_ClkInitStruct.IC11Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1; + RCC_ClkInitStruct.IC11Selection.ClockDivider = 3; + RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV1; + RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV1; + RCC_ClkInitStruct.APB5CLKDivider = RCC_APB5_DIV1; + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct) != HAL_OK) { + /* Initialization Error */ + Error_Handler(); + } + + /** Initializes the peripherals clock + */ + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USBOTGHS1; + PeriphClkInitStruct.UsbOtgHs1ClockSelection = RCC_USBPHY1REFCLKSOURCE_HSE_DIRECT; + + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + /* Initialization Error */ + Error_Handler(); + } + + /** Set USB OTG HS PHY1 Reference Clock Source */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USBPHY1; + PeriphClkInitStruct.UsbPhy1ClockSelection = RCC_USBPHY1REFCLKSOURCE_HSE_DIRECT; + + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + /* Initialization Error */ + Error_Handler(); + } +} + +//--------------------------------------------------------------------+ +// USB PD +//--------------------------------------------------------------------+ +static I2C_HandleTypeDef i2c_handle = { + .Instance = I2C2, + .Init = { + .Timing = 0x20C0EDFF, + .OwnAddress1 = 0, + .AddressingMode = I2C_ADDRESSINGMODE_7BIT, + .DualAddressMode = I2C_DUALADDRESS_DISABLE, + .OwnAddress2 = 0, + .OwnAddress2Masks = I2C_OA2_NOMASK, + .GeneralCallMode = I2C_GENERALCALL_DISABLE, + .NoStretchMode = I2C_NOSTRETCH_DISABLE, + }}; +static TCPP0203_Object_t tcpp0203_obj = {0}; + +int32_t board_tcpp0203_init(void) { + board_pindef_t *pindef = &board_pindef[PINID_TCPP0203_EN]; + HAL_GPIO_WritePin(pindef->port, pindef->pin_init.Pin, GPIO_PIN_SET); + + __HAL_RCC_I2C2_CLK_ENABLE(); + __HAL_RCC_I2C2_FORCE_RESET(); + __HAL_RCC_I2C2_RELEASE_RESET(); + if (HAL_I2C_Init(&i2c_handle) != HAL_OK) { + return HAL_ERROR; + } + + NVIC_SetPriority(EXTI10_IRQn, 12); + NVIC_EnableIRQ(EXTI10_IRQn); + + return 0; +} + +int32_t board_tcpp0203_deinit(void) { + return 0; +} + +int32_t i2c_readreg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { + TU_ASSERT(HAL_OK == HAL_I2C_Mem_Read(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000)); + return 0; +} + +int32_t i2c_writereg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { + TU_ASSERT(HAL_OK == HAL_I2C_Mem_Write(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000)); + return 0; +} + +static inline void board_init2(void) { + TCPP0203_IO_t io_ctx; + + io_ctx.Address = TCPP0203_I2C_ADDRESS_X68; + io_ctx.Init = board_tcpp0203_init; + io_ctx.DeInit = board_tcpp0203_deinit; + io_ctx.ReadReg = i2c_readreg; + io_ctx.WriteReg = i2c_writereg; + + TU_ASSERT(TCPP0203_RegisterBusIO(&tcpp0203_obj, &io_ctx) == TCPP0203_OK, ); + + TU_ASSERT(TCPP0203_Init(&tcpp0203_obj) == TCPP0203_OK, ); + + TU_ASSERT(TCPP0203_SetPowerMode(&tcpp0203_obj, TCPP0203_POWER_MODE_NORMAL) == TCPP0203_OK, ); +} + +void board_vbus_set(uint8_t rhport, bool state) { + (void) state; + if (rhport == 1) { + TU_ASSERT(TCPP0203_SetGateDriverProvider(&tcpp0203_obj, TCPP0203_GD_PROVIDER_SWITCH_CLOSED) == TCPP0203_OK, ); + } +} + +void EXTI10_IRQHandler(void) { + __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_10); + if (tcpp0203_obj.IsInitialized) { + TU_ASSERT(TCPP0203_SetPowerMode(&tcpp0203_obj, TCPP0203_POWER_MODE_NORMAL) == TCPP0203_OK, ); + TU_ASSERT(TCPP0203_SetGateDriverProvider(&tcpp0203_obj, TCPP0203_GD_PROVIDER_SWITCH_CLOSED) == TCPP0203_OK, ); + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hw/bsp/stm32n6/boards/stm32n6570dk/board.mk b/hw/bsp/stm32n6/boards/stm32n6570dk/board.mk new file mode 100644 index 000000000..05717699c --- /dev/null +++ b/hw/bsp/stm32n6/boards/stm32n6570dk/board.mk @@ -0,0 +1,17 @@ +MCU_VARIANT = stm32n657xx +CFLAGS += -DSTM32N657xx +JLINK_DEVICE = stm32n6xx + +LD_FILE_GCC = $(BOARD_PATH)/STM32N657XX_AXISRAM2_fsbl.ld + +# flash target using on-board stlink +flash: flash-stlink + +PORT = 1 + +SRC_C += \ + $(ST_TCPP0203)/tcpp0203.c \ + $(ST_TCPP0203)/tcpp0203_reg.c \ + +INC += \ + $(TOP)/$(ST_TCPP0203) \ From eda5c3a5d1f7c4d402acbd739d025ee84eb39828 Mon Sep 17 00:00:00 2001 From: Aleksei Musin Date: Sun, 24 Aug 2025 17:21:20 +0400 Subject: [PATCH 337/382] STM32N6570-DK gets listed in boards.rst --- docs/reference/boards.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 289ec543a..2368dd9e5 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -292,6 +292,7 @@ stm32l412nucleo STM32 L412 Nucleo stm32l4 https://www.s stm32l476disco STM32 L476 Disco stm32l4 https://www.st.com/en/evaluation-tools/32l476gdiscovery.html stm32l4p5nucleo STM32 L4P5 Nucleo stm32l4 https://www.st.com/en/evaluation-tools/nucleo-l4p5zg.html stm32l4r5nucleo STM32 L4R5 Nucleo stm32l4 https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html +stm32n6570dk STM32 N6570-DK stm32n6 https://www.st.com/en/evaluation-tools/stm32n6570-dk.html stm32n657nucleo STM32 N657X0-Q Nucleo stm32n6 https://www.st.com/en/evaluation-tools/nucleo-n657x0-q.html b_u585i_iot2a STM32 B-U585i IOT2A Discovery kit stm32u5 https://www.st.com/en/evaluation-tools/b-u585i-iot02a.html stm32u545nucleo STM32 U545 Nucleo stm32u5 https://www.st.com/en/evaluation-tools/nucleo-u545re-q.html From 6f2b5fc4952e0fc730466a8756ce6427c33ce2b7 Mon Sep 17 00:00:00 2001 From: Mitsumine Suzu <60875431+verylowfreq@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:52:52 +0900 Subject: [PATCH 338/382] Remove dynamic memory allocation --- src/portable/wch/hcd_ch32_usbfs.c | 46 ++++++++++++++----------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index 449908658..ff34ae17a 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -84,6 +84,10 @@ typedef struct usb_edpt { // Data toggle (0 or not 0) for DATA0/1 uint8_t data_toggle; + + bool is_nak_pending; + uint16_t buflen; + uint8_t* buf; } usb_edpt_t; static usb_edpt_t usb_edpt_list[CFG_TUH_DEVICE_MAX * 6] = {}; @@ -130,6 +134,9 @@ static usb_edpt_t *add_edpt_record(uint8_t dev_addr, uint8_t ep_addr, uint16_t m slot->max_packet_size = max_packet_size; slot->xfer_type = xfer_type; slot->data_toggle = 0; + slot->is_nak_pending = false; + slot->buflen = 0; + slot->buf = NULL; slot->configured = true; @@ -354,28 +361,22 @@ void hcd_int_disable(uint8_t rhport) { interrupt_enabled = false; } -typedef struct { - uint8_t rhport; - uint8_t dev_addr; - uint8_t ep_addr; - uint16_t buflen; - uint8_t* buf; -} xfer_retry_param_t; static void xfer_retry(void* _params) { LOG_CH32_USBFSH("xfer_retry()\r\n"); - xfer_retry_param_t* params = (xfer_retry_param_t*)_params; + usb_edpt_t* edpt_info = (usb_edpt_t*)_params; if (usb_current_xfer_info.nak_pending) { usb_current_xfer_info.nak_pending = false; + edpt_info->is_nak_pending = false; - uint8_t dev_addr = params->dev_addr; - uint8_t ep_addr = params->ep_addr; - uint16_t buflen = params->buflen; - uint8_t* buf = params->buf; - free(params); + uint8_t dev_addr = edpt_info->dev_addr; + uint8_t ep_addr = edpt_info->ep_addr; + uint16_t buflen = edpt_info->buflen; + uint8_t* buf = edpt_info->buf; - usb_edpt_t* edpt_info = get_edpt_record(dev_addr, ep_addr); - if (edpt_info) { + // Check connectivity + usb_edpt_t* edpt_info_current = get_edpt_record(dev_addr, ep_addr); + if (edpt_info_current) { hcd_edpt_xfer(0, dev_addr, ep_addr, buf, buflen); } } @@ -498,15 +499,10 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { usb_current_xfer_info.is_busy = false; usb_current_xfer_info.nak_pending = true; - xfer_retry_param_t* param_buf = malloc(sizeof(xfer_retry_param_t)); - xfer_retry_param_t param = { - .rhport = 0, - .dev_addr = dev_addr, - .ep_addr = ep_addr, - .buflen = usb_current_xfer_info.bufferlen, - .buf = usb_current_xfer_info.buffer - }; - memcpy(param_buf, ¶m, sizeof(xfer_retry_param_t)); + + edpt_info->is_nak_pending = true; + edpt_info->buflen = usb_current_xfer_info.bufferlen; + edpt_info->buf = usb_current_xfer_info.buffer; hcd_event_t event = { .rhport = rhport, @@ -514,7 +510,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { .event_id = USBH_EVENT_FUNC_CALL, .func_call = { .func = xfer_retry, - .param = param_buf + .param = edpt_info } }; hcd_event_handler(&event, in_isr); From 12ee78df308aa80d6c2ef34bff1be0df38939027 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sun, 24 Aug 2025 17:19:51 +0200 Subject: [PATCH 339/382] Fix osal_spin_unlock for mynewt Mynewt version for osal_spin_unlock() called OS_ENTER_CRITICAL instead of OS_EXIT_CRITICAL. Signed-off-by: Jerzy Kasenberg --- src/osal/osal_mynewt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index ee95e684f..6d51f8ec3 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -63,7 +63,7 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, if (!TUP_MCU_MULTIPLE_CORE && in_isr) { return; // single core MCU does not need to lock in ISR } - OS_ENTER_CRITICAL(*ctx); + OS_EXIT_CRITICAL(*ctx); } //--------------------------------------------------------------------+ From 38f41f5fa28943086cd36653e0914fd59cb7ed03 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Thu, 28 Aug 2025 15:35:55 +0200 Subject: [PATCH 340/382] fix(dcd/dwc2): Fix reset procedure for versions >=4.20a --- src/portable/synopsys/dwc2/dwc2_common.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index b001f343d..9b8333ad2 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2024 Ha Thach (tinyusb.org) + * Copyright (c) 2024-2025 Ha Thach (tinyusb.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -45,11 +45,14 @@ // //-------------------------------------------------------------------- static void reset_core(dwc2_regs_t* dwc2) { + // load gsnpsid (it is not readable after reset is asserted) + uint32_t gsnpsid = dwc2->gsnpsid; + // reset core dwc2->grstctl |= GRSTCTL_CSRST; - if ((dwc2->gsnpsid & DWC2_CORE_REV_MASK) < (DWC2_CORE_REV_4_20a & DWC2_CORE_REV_MASK)) { - // prior v42.0 CSRST is self-clearing + if ((gsnpsid & DWC2_CORE_REV_MASK) < (DWC2_CORE_REV_4_20a & DWC2_CORE_REV_MASK)) { + // prior v4.20a CSRST is self-clearing while (dwc2->grstctl & GRSTCTL_CSRST) {} } else { // From v4.20a CSRST bit is write only, CSRT_DONE (w1c) is introduced for checking. From f5d04833bb5841930476cc666193f2f362aef228 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Sep 2025 13:30:20 +0700 Subject: [PATCH 341/382] use tusb_time_millis_api() instead of board_millis() make loopdelay() always inline --- src/portable/wch/hcd_ch32_usbfs.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/portable/wch/hcd_ch32_usbfs.c b/src/portable/wch/hcd_ch32_usbfs.c index ff34ae17a..200136906 100644 --- a/src/portable/wch/hcd_ch32_usbfs.c +++ b/src/portable/wch/hcd_ch32_usbfs.c @@ -57,20 +57,18 @@ TU_ATTR_ALIGNED(4) static uint8_t USBFS_TX_Buf[USBFS_TX_BUF_LEN]; #define LOG_CH32_USBFSH(...) TU_LOG3(__VA_ARGS__) // Busywait for delay microseconds/nanoseconds -static void loopdelay(uint32_t count) -{ - volatile uint32_t c = count / 3; - if (c == 0) { return; } - // while (c-- != 0); - asm volatile( - "1: \n" // loop label - " addi %0, %0, -1 \n" // c-- - " bne %0, zero, 1b \n" // if (c != 0) goto loop - : "+r"(c) // c is input/output operand +TU_ATTR_ALWAYS_INLINE static inline void loopdelay(uint32_t count) { + volatile uint32_t c = count / 3; + if (c == 0) { return; } + // while (c-- != 0); + asm volatile( + "1: \n" // loop label + " addi %0, %0, -1 \n" // c-- + " bne %0, zero, 1b \n" // if (c != 0) goto loop + : "+r"(c) // c is input/output operand ); } - // Endpoint status typedef struct usb_edpt { // Is this a valid struct @@ -346,7 +344,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { uint32_t hcd_frame_number(uint8_t rhport) { (void) rhport; - return board_millis(); + return tusb_time_millis_api(); } void hcd_int_enable(uint8_t rhport) { @@ -489,7 +487,7 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) { return; } else if (response_pid == USB_PID_NAK) { LOG_CH32_USBFSH("NAK reposense\r\n"); - uint32_t elapsed_time = board_millis() - usb_current_xfer_info.start_ms; + uint32_t elapsed_time = tusb_time_millis_api() - usb_current_xfer_info.start_ms; (void)elapsed_time; if (edpt_info->xfer_type == TUSB_XFER_INTERRUPT) { usb_current_xfer_info.is_busy = false; @@ -577,7 +575,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *b usb_current_xfer_info.ep_addr = ep_addr; usb_current_xfer_info.buffer = buffer; usb_current_xfer_info.bufferlen = buflen; - usb_current_xfer_info.start_ms = board_millis(); + usb_current_xfer_info.start_ms = tusb_time_millis_api(); usb_current_xfer_info.xferred_len = 0; usb_current_xfer_info.nak_pending = false; @@ -628,7 +626,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet uint8_t ep_addr = (setup_packet[0] & 0x80) ? 0x80 : 0x00; usb_current_xfer_info.dev_addr = dev_addr; usb_current_xfer_info.ep_addr = ep_addr; - usb_current_xfer_info.start_ms = board_millis(); + usb_current_xfer_info.start_ms = tusb_time_millis_api(); usb_current_xfer_info.buffer = USBFS_TX_Buf; usb_current_xfer_info.bufferlen = setup_packet_datalen; usb_current_xfer_info.xferred_len = 0; From c5a390950f8616f42917bc6ecd8c8e528cdda49e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 3 Sep 2025 17:20:54 +0700 Subject: [PATCH 342/382] add at32f415 dwc2 info --- src/portable/synopsys/dwc2/dwc2_info.md | 116 ++++++++++++------------ src/portable/synopsys/dwc2/dwc2_info.py | 1 + 2 files changed, 59 insertions(+), 58 deletions(-) diff --git a/src/portable/synopsys/dwc2/dwc2_info.md b/src/portable/synopsys/dwc2/dwc2_info.md index 00685e7ad..e6b7820bc 100644 --- a/src/portable/synopsys/dwc2/dwc2_info.md +++ b/src/portable/synopsys/dwc2/dwc2_info.md @@ -1,58 +1,58 @@ -| | AT32 F405 FS | AT32 F405 HS | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5/H7RS/N6 HS | XMC4500 | GD32VF103 | -|:---------------------------|:---------------|:---------------|:----------------|:-------------|:--------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:---------------------|:-------------|:------------| -| GUID | 0x00002000 | 0x00000000 | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00AEC000 | 0x00001000 | -| GSNPSID | 0x4F54400A | 0x4F54400A | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54292A | 0x00000000 | -| - specs version | 4.00a | 4.00a | 2.80a | 3.30a | 4.00a | 4.00a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 2.92a | 0.00W | -| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | -| GHWCFG2 | 0x228FDD00 | 0x229FDDD0 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228F5930 | 0x00000000 | -| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | HNP SRP | HNP SRP | -| - arch | Slave only | DMA internal | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | Slave only | -| - single_point | hub | hub | hub | hub | n/a | hub | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | n/a | hub | -| - hs_phy_type | n/a | UTMI+/ULPI | UTMI+ | n/a | n/a | UTMI+/ULPI | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | n/a | n/a | -| - fs_phy_type | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Shared ULPI | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | Dedicated | n/a | -| - num_dev_ep | 7 | 7 | 7 | 6 | 6 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | -| - num_host_ch | 15 | 15 | 7 | 13 | 7 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 13 | 0 | -| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - mul_proc_intrpt | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - nptx_q_depth | 8 | 8 | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - ptx_q_depth | 8 | 8 | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | -| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| GHWCFG3 | 0x020004E8 | 0x03F006E8 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | -| - xfer_size_width | 8 | 8 | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | -| - packet_size_width | 6 | 6 | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | -| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - i2c_enable | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | -| - vendor_ctrl_itf | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | -| - optional_feature_removed | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - synch_reset | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - otg_adp_support | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - battery_charger_support | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | -| - dfifo_depth | 512 | 1008 | 4080 | 498 | 200 | 896 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 634 | 0 | -| GHWCFG4 | 0x1FF0A020 | 0x1FF0A020 | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | -| - num_dev_period_in_ep | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - partial_powerdown | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - ahb_freq_min | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - enhanced_lpm_support | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - phy_data_width | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8/16 bit | 8 bit | -| - ctrl_ep_num | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - iddg_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - vbus_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - a_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - b_valid_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - session_end_filter | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - dedicated_fifos | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - num_dev_in_eps | 7 | 7 | 7 | 6 | 4 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | -| - dma_desc_enable | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | -| - dma_desc_dynamic | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | +| | AT32 F405 FS | AT32 F405 HS | AT32 F415 | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5/H7RS/N6 HS | XMC4500 | GD32VF103 | +|:---------------------------|:---------------|:---------------|:------------|:----------------|:-------------|:--------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:---------------------|:-------------|:------------| +| GUID | 0x00002000 | 0x00000000 | 0x00001000 | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00AEC000 | 0x00001000 | +| GSNPSID | 0x4F54400A | 0x4F54400A | 0x4F54400A | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54292A | 0x00000000 | +| - specs version | 4.00a | 4.00a | 4.00a | 2.80a | 3.30a | 4.00a | 4.00a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 2.92a | 0.00W | +| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | +| GHWCFG2 | 0x228FDD00 | 0x229FDDD0 | 0x228DCD00 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228F5930 | 0x00000000 | +| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | HNP SRP | HNP SRP | +| - arch | Slave only | DMA internal | Slave only | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | Slave only | +| - single_point | hub | hub | hub | hub | hub | n/a | hub | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | n/a | hub | +| - hs_phy_type | n/a | UTMI+/ULPI | n/a | UTMI+ | n/a | n/a | UTMI+/ULPI | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | n/a | n/a | +| - fs_phy_type | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Shared ULPI | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | Dedicated | n/a | +| - num_dev_ep | 7 | 7 | 3 | 7 | 6 | 6 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | +| - num_host_ch | 15 | 15 | 7 | 7 | 13 | 7 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 13 | 0 | +| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - mul_proc_intrpt | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - nptx_q_depth | 8 | 8 | 8 | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - ptx_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | +| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| GHWCFG3 | 0x020004E8 | 0x03F006E8 | 0x020004E8 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | +| - xfer_size_width | 8 | 8 | 8 | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | +| - packet_size_width | 6 | 6 | 6 | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | +| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - i2c_enable | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | +| - vendor_ctrl_itf | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | +| - optional_feature_removed | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - synch_reset | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - otg_adp_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - battery_charger_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | +| - dfifo_depth | 512 | 1008 | 512 | 4080 | 498 | 200 | 896 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 634 | 0 | +| GHWCFG4 | 0x1FF0A020 | 0x1FF0A020 | 0x0000000F | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | +| - num_dev_period_in_ep | 0 | 0 | 15 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - partial_powerdown | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - ahb_freq_min | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - enhanced_lpm_support | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - phy_data_width | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8/16 bit | 8 bit | +| - ctrl_ep_num | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - iddg_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - vbus_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - a_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - b_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - session_end_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - dedicated_fifos | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - num_dev_in_eps | 7 | 7 | 0 | 7 | 6 | 4 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | +| - dma_desc_enable | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | +| - dma_desc_dynamic | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py index bc5ad9a7b..a90150632 100755 --- a/src/portable/synopsys/dwc2/dwc2_info.py +++ b/src/portable/synopsys/dwc2/dwc2_info.py @@ -11,6 +11,7 @@ dwc2_reg_list = ['GUID', 'GSNPSID', 'GHWCFG1', 'GHWCFG2', 'GHWCFG3', 'GHWCFG4'] dwc2_reg_value = { 'AT32 F405 FS': [0x00002000, 0x4F54400A, 0x00000000, 0x228FDD00, 0x020004E8, 0x1FF0A020], 'AT32 F405 HS': [0x00000000, 0x4F54400A, 0x00000000, 0x229FDDD0, 0x03F006E8, 0x1FF0A020], + 'AT32 F415': [0x00001000, 0x4F54400A, 0x00000000, 0x228DCD00, 0x020004E8, 0x0F], 'BCM2711 (Pi4)': [0x2708A000, 0x4F54280A, 0, 0x228DDD50, 0xFF000E8, 0x1FF00020], 'EFM32GG': [0, 0x4F54330A, 0, 0x228F5910, 0x01F204E8, 0x1BF08030], 'ESP32-S2/S3': [0, 0x4F54400A, 0, 0x224DD930, 0x0C804B5, 0xD3F0A030], From 08f3971804b5c4974c32bd89349b65669c0c412d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Sep 2025 10:37:05 +0000 Subject: [PATCH 343/382] Initial plan From da9284e88baefc6d0e5f7c624f8f7da7f4d6aed0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 3 Sep 2025 10:42:17 +0000 Subject: [PATCH 344/382] Fix obsolete cnt assignment in _tu_fifo_peek() overflow check Co-authored-by: hathach <249515+hathach@users.noreply.github.com> --- src/common/tusb_fifo.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index ecf002b09..f7679556f 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -428,7 +428,6 @@ static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wr_idx, uint16 if ( cnt > f->depth ) { rd_idx = _ff_correct_read_index(f, wr_idx); - cnt = f->depth; } uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); From a96ee81a7ddc03f04a837d949c291f22362d6cb4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Sep 2025 10:36:15 +0700 Subject: [PATCH 345/382] remove duplicated enum --- src/class/hid/hid.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index 0fc0e1377..bbc58af80 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -994,9 +994,7 @@ enum { HID_USAGE_CONSUMER_FAST_FORWARD = 0x00B3, HID_USAGE_CONSUMER_REWIND = 0x00B4, HID_USAGE_CONSUMER_SCAN_NEXT_TRACK = 0x00B5, - HID_USAGE_CONSUMER_SCAN_NEXT = 0x00B5, HID_USAGE_CONSUMER_SCAN_PREVIOUS_TRACK = 0x00B6, - HID_USAGE_CONSUMER_SCAN_PREVIOUS = 0x00B6, HID_USAGE_CONSUMER_STOP = 0x00B7, HID_USAGE_CONSUMER_EJECT = 0x00B8, HID_USAGE_CONSUMER_RANDOM_PLAY = 0x00B9, @@ -1097,7 +1095,6 @@ enum { // Configuration // Sel 15.15 HID_USAGE_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x0183, - HID_USAGE_CONSUMER_AL_CONSUMER_CONTROL = 0x0183, // Configuration // Sel 15.15 HID_USAGE_CONSUMER_AL_WORD_PROCESSOR = 0x0184, @@ -1117,7 +1114,6 @@ enum { HID_USAGE_CONSUMER_AL_CALCULATOR = 0x0192, HID_USAGE_CONSUMER_AL_A_V_CAPTURE_PLAYBACK = 0x0193, HID_USAGE_CONSUMER_AL_LOCAL_MACHINE_BROWSER = 0x0194, - HID_USAGE_CONSUMER_AL_LOCAL_BROWSER = 0x0194, HID_USAGE_CONSUMER_AL_LAN_WAN_BROWSER = 0x0195, HID_USAGE_CONSUMER_AL_INTERNET_BROWSER = 0x0196, HID_USAGE_CONSUMER_AL_REMOTE_NETWORKING_ISP = 0x0197, From 02e5c9501c1846c425fc74350efbc4f599466813 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Sep 2025 06:17:41 +0000 Subject: [PATCH 346/382] Initial plan From fe42b3a7ccefb2a65281c5b65b1897404b53b726 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Sep 2025 06:29:43 +0000 Subject: [PATCH 347/382] Update STM32 CMSIS dependencies to fix HSITRIM register bug Co-authored-by: hathach <249515+hathach@users.noreply.github.com> --- hw/mcu/st/cmsis_device_l4 | 1 + hw/mcu/st/stm32l4xx_hal_driver | 1 + lib/CMSIS_5 | 1 + lib/FreeRTOS-Kernel | 1 + lib/lwip | 1 + tools/get_deps.py | 20 ++++++++++---------- tools/uf2 | 1 + 7 files changed, 16 insertions(+), 10 deletions(-) create mode 160000 hw/mcu/st/cmsis_device_l4 create mode 160000 hw/mcu/st/stm32l4xx_hal_driver create mode 160000 lib/CMSIS_5 create mode 160000 lib/FreeRTOS-Kernel create mode 160000 lib/lwip create mode 160000 tools/uf2 diff --git a/hw/mcu/st/cmsis_device_l4 b/hw/mcu/st/cmsis_device_l4 new file mode 160000 index 000000000..a2530753e --- /dev/null +++ b/hw/mcu/st/cmsis_device_l4 @@ -0,0 +1 @@ +Subproject commit a2530753e86dd326a75467d28feb92e2ba7d0df2 diff --git a/hw/mcu/st/stm32l4xx_hal_driver b/hw/mcu/st/stm32l4xx_hal_driver new file mode 160000 index 000000000..aee3d5bf2 --- /dev/null +++ b/hw/mcu/st/stm32l4xx_hal_driver @@ -0,0 +1 @@ +Subproject commit aee3d5bf283ae5df87532b781bdd01b7caf256fc diff --git a/lib/CMSIS_5 b/lib/CMSIS_5 new file mode 160000 index 000000000..2b7495b85 --- /dev/null +++ b/lib/CMSIS_5 @@ -0,0 +1 @@ +Subproject commit 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c diff --git a/lib/FreeRTOS-Kernel b/lib/FreeRTOS-Kernel new file mode 160000 index 000000000..cc0e0707c --- /dev/null +++ b/lib/FreeRTOS-Kernel @@ -0,0 +1 @@ +Subproject commit cc0e0707c0c748713485b870bb980852b210877f diff --git a/lib/lwip b/lib/lwip new file mode 160000 index 000000000..159e31b68 --- /dev/null +++ b/lib/lwip @@ -0,0 +1 @@ +Subproject commit 159e31b689577dbf69cf0683bbaffbd71fa5ee10 diff --git a/tools/get_deps.py b/tools/get_deps.py index ce838e427..8f316aedc 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -77,31 +77,31 @@ deps_optional = { 'fb56b1b70c73b74eacda2a4bcc36886444364ab3', 'stm32c0'], 'hw/mcu/st/cmsis_device_f0': ['https://github.com/STMicroelectronics/cmsis_device_f0.git', - '2fc25ee22264bc27034358be0bd400b893ef837e', + 'cbb5da5d48b4b5f2efacdc2f033be30f9d29889f', 'stm32f0'], 'hw/mcu/st/cmsis_device_f1': ['https://github.com/STMicroelectronics/cmsis_device_f1.git', - '6601104a6397299b7304fd5bcd9a491f56cb23a6', + 'c8e9a4a4f16b6d2cb2a2083cbe5161025280fb22', 'stm32f1'], 'hw/mcu/st/cmsis_device_f2': ['https://github.com/STMicroelectronics/cmsis_device_f2.git', - '182fcb3681ce116816feb41b7764f1b019ce796f', + '49321f1e4d2bd3e65687b37f2652a28ea7983674', 'stm32f2'], 'hw/mcu/st/cmsis_device_f3': ['https://github.com/STMicroelectronics/cmsis_device_f3.git', - '5e4ee5ed7a7b6c85176bb70a9fd3c72d6eb99f1b', + '5558e64e3675a1e1fcb1c71f468c7c407c1b1134', 'stm32f3'], 'hw/mcu/st/cmsis_device_f4': ['https://github.com/STMicroelectronics/cmsis_device_f4.git', - '2615e866fa48fe1ff1af9e31c348813f2b19e7ec', + '0fa0e489e053fa1ca7790bb40b4d76458f64c55d', 'stm32f4'], 'hw/mcu/st/cmsis_device_f7': ['https://github.com/STMicroelectronics/cmsis_device_f7.git', - '25b0463439303b7a38f0d27b161f7d2f3c096e79', + '2352e888e821aa0f4fe549bd5ea81d29c67a3222', 'stm32f7'], 'hw/mcu/st/cmsis_device_g0': ['https://github.com/STMicroelectronics/cmsis_device_g0.git', - '3a23e1224417f3f2d00300ecd620495e363f2094', + 'f484fe852535f913a02ee79787eafa74dd7f9488', 'stm32g0'], 'hw/mcu/st/cmsis_device_g4': ['https://github.com/STMicroelectronics/cmsis_device_g4.git', - 'ce822adb1dc552b3aedd13621edbc7fdae124878', + '7c39c32593b03764aaa57531588b8bf7cdd443a5', 'stm32g4'], 'hw/mcu/st/cmsis_device_h7': ['https://github.com/STMicroelectronics/cmsis_device_h7.git', - '60dc2c913203dc8629dc233d4384dcc41c91e77f', + '45b818cab6ee2806e3a27c80e330957223424392', 'stm32h7'], 'hw/mcu/st/cmsis_device_h7rs': ['https://github.com/STMicroelectronics/cmsis_device_h7rs.git', '832649d1fd09bd901e9f68e979522e5c209ebf20', @@ -116,7 +116,7 @@ deps_optional = { '7f16ec0a1c4c063f84160b4cc6bf88ad554a823e', 'stm32l1'], 'hw/mcu/st/cmsis_device_l4': ['https://github.com/STMicroelectronics/cmsis_device_l4.git', - '6ca7312fa6a5a460b5a5a63d66da527fdd8359a6', + 'a2530753e86dd326a75467d28feb92e2ba7d0df2', 'stm32l4'], 'hw/mcu/st/cmsis_device_l5': ['https://github.com/STMicroelectronics/cmsis_device_l5.git', 'd922865fc0326a102c26211c44b8e42f52c1e53d', diff --git a/tools/uf2 b/tools/uf2 new file mode 160000 index 000000000..c594542b2 --- /dev/null +++ b/tools/uf2 @@ -0,0 +1 @@ +Subproject commit c594542b2faa01cc33a2b97c9fbebc38549df80a From 640f57db2e061112bc6d38afd1f8c020f9d56581 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Sep 2025 06:30:22 +0000 Subject: [PATCH 348/382] Remove accidentally committed dependency directories Co-authored-by: hathach <249515+hathach@users.noreply.github.com> --- hw/mcu/st/cmsis_device_l4 | 1 - hw/mcu/st/stm32l4xx_hal_driver | 1 - lib/CMSIS_5 | 1 - lib/FreeRTOS-Kernel | 1 - lib/lwip | 1 - tools/uf2 | 1 - 6 files changed, 6 deletions(-) delete mode 160000 hw/mcu/st/cmsis_device_l4 delete mode 160000 hw/mcu/st/stm32l4xx_hal_driver delete mode 160000 lib/CMSIS_5 delete mode 160000 lib/FreeRTOS-Kernel delete mode 160000 lib/lwip delete mode 160000 tools/uf2 diff --git a/hw/mcu/st/cmsis_device_l4 b/hw/mcu/st/cmsis_device_l4 deleted file mode 160000 index a2530753e..000000000 --- a/hw/mcu/st/cmsis_device_l4 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a2530753e86dd326a75467d28feb92e2ba7d0df2 diff --git a/hw/mcu/st/stm32l4xx_hal_driver b/hw/mcu/st/stm32l4xx_hal_driver deleted file mode 160000 index aee3d5bf2..000000000 --- a/hw/mcu/st/stm32l4xx_hal_driver +++ /dev/null @@ -1 +0,0 @@ -Subproject commit aee3d5bf283ae5df87532b781bdd01b7caf256fc diff --git a/lib/CMSIS_5 b/lib/CMSIS_5 deleted file mode 160000 index 2b7495b85..000000000 --- a/lib/CMSIS_5 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2b7495b8535bdcb306dac29b9ded4cfb679d7e5c diff --git a/lib/FreeRTOS-Kernel b/lib/FreeRTOS-Kernel deleted file mode 160000 index cc0e0707c..000000000 --- a/lib/FreeRTOS-Kernel +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cc0e0707c0c748713485b870bb980852b210877f diff --git a/lib/lwip b/lib/lwip deleted file mode 160000 index 159e31b68..000000000 --- a/lib/lwip +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 159e31b689577dbf69cf0683bbaffbd71fa5ee10 diff --git a/tools/uf2 b/tools/uf2 deleted file mode 160000 index c594542b2..000000000 --- a/tools/uf2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c594542b2faa01cc33a2b97c9fbebc38549df80a From f6ca80ab13997d8fdee084d218c22ae15d734e2a Mon Sep 17 00:00:00 2001 From: zhiqiang Date: Thu, 4 Sep 2025 14:38:27 +0800 Subject: [PATCH 349/382] modified the bsp files of at32 to make them work better --- docs/reference/boards.rst | 26 ++-- .../boards/at_start_f402/board.cmake | 8 ++ .../at32f402_405/boards/at_start_f402/board.h | 74 +++++++++++ .../boards/at_start_f402/board.mk | 7 ++ .../boards/at_start_f405/board.cmake | 9 ++ .../at32f402_405/boards/at_start_f405/board.h | 106 +--------------- .../boards/at_start_f405/board.mk | 4 + hw/bsp/at32f402_405/family.c | 32 ++--- hw/bsp/at32f402_405/family.cmake | 23 +++- hw/bsp/at32f402_405/family.mk | 28 ++++- .../boards/at_start_f403a/board.cmake | 2 +- .../boards/at_start_f403a/board.mk | 2 +- .../boards/at_start_f407/board.cmake | 8 ++ .../boards/at_start_f407/board.h | 71 +++++++++++ .../boards/at_start_f407/board.mk | 7 ++ hw/bsp/at32f403a_407/family.c | 4 +- hw/bsp/at32f413/boards/at_start_f413/board.h | 2 +- hw/bsp/at32f415/boards/at_start_f415/board.h | 2 +- hw/bsp/at32f423/boards/at_start_f423/board.h | 2 +- hw/bsp/at32f425/boards/at_start_f425/board.h | 2 +- .../boards/at_start_f435/board.cmake | 8 ++ .../at32f435_437/boards/at_start_f435/board.h | 74 +++++++++++ .../boards/at_start_f435/board.mk | 7 ++ .../at32f435_437/boards/at_start_f437/board.h | 117 +----------------- hw/bsp/at32f435_437/family.c | 40 +++--- hw/bsp/at32f435_437/family.cmake | 7 +- hw/bsp/at32f435_437/family.mk | 5 +- 27 files changed, 384 insertions(+), 293 deletions(-) create mode 100644 hw/bsp/at32f402_405/boards/at_start_f402/board.cmake create mode 100644 hw/bsp/at32f402_405/boards/at_start_f402/board.h create mode 100644 hw/bsp/at32f402_405/boards/at_start_f402/board.mk create mode 100644 hw/bsp/at32f403a_407/boards/at_start_f407/board.cmake create mode 100644 hw/bsp/at32f403a_407/boards/at_start_f407/board.h create mode 100644 hw/bsp/at32f403a_407/boards/at_start_f407/board.mk create mode 100644 hw/bsp/at32f435_437/boards/at_start_f435/board.cmake create mode 100644 hw/bsp/at32f435_437/boards/at_start_f435/board.h create mode 100644 hw/bsp/at32f435_437/boards/at_start_f435/board.mk diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index f4f2f6d1f..d984b3529 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -30,18 +30,20 @@ max78002evkit MAX78002 EVKIT maxim https://www.analog.com/en/resources/e Artery ----- -========================= ==================================== ============= ==================================================== ====== -Board Name Family URL Note -========================= ==================================== ============= ==================================================== ====== -at_start_f405 AT-START-F405 at32f402_405 https://www.arterychip.com/en/product/AT32F405.jsp -at_start_f403a AT-START-F403a at32f403a_407 https://www.arterychip.com/en/product/AT32F403.jsp -at32f403a_weact_blackpill WeAct Studio BlackPill AT32F403ACGU7 at32f403a_407 https://github.com/WeActStudio/WeActStudio.BlackPill -at_start_f413 AT-START-F413 at32f413 https://www.arterychip.com/en/product/AT32F413.jsp -at_start_f415 AT-START-F415 at32f415 https://www.arterychip.com/en/product/AT32F415.jsp -at_start_f423 AT-START-F423 at32f423 https://www.arterychip.com/en/product/AT32F423.jsp -at_start_f425 AT-START-F425 at32f425 https://www.arterychip.com/en/product/AT32F425.jsp -at_start_f437 AT-START-F437 at32f435_437 https://www.arterychip.com/en/product/AT32F437.jsp -========================= ==================================== ============= ==================================================== ====== +============== ============== ============= ================================================== ====== +Board Name Family URL Note +============== ============== ============= ================================================== ====== +at_start_f402 AT-START-F402 at32f402_405 https://www.arterychip.com/en/product/AT32F402.jsp +at_start_f405 AT-START-F405 at32f402_405 https://www.arterychip.com/en/product/AT32F405.jsp +at_start_f403a AT-START-F403a at32f403a_407 https://www.arterychip.com/en/product/AT32F403A.jsp +at_start_f407 AT-START-F407 at32f403a_407 https://www.arterychip.com/en/product/AT32F407.jsp +at_start_f413 AT-START-F413 at32f413 https://www.arterychip.com/en/product/AT32F413.jsp +at_start_f415 AT-START-F415 at32f415 https://www.arterychip.com/en/product/AT32F415.jsp +at_start_f423 AT-START-F423 at32f423 https://www.arterychip.com/en/product/AT32F423.jsp +at_start_f425 AT-START-F425 at32f425 https://www.arterychip.com/en/product/AT32F425.jsp +at_start_f435 AT-START-F435 at32f435_435 https://www.arterychip.com/en/product/AT32F435.jsp +at_start_f437 AT-START-F437 at32f435_437 https://www.arterychip.com/en/product/AT32F437.jsp +============== ============== ============= ================================================== ====== Bridgetek --------- diff --git a/hw/bsp/at32f402_405/boards/at_start_f402/board.cmake b/hw/bsp/at32f402_405/boards/at_start_f402/board.cmake new file mode 100644 index 000000000..4e7755c0f --- /dev/null +++ b/hw/bsp/at32f402_405/boards/at_start_f402/board.cmake @@ -0,0 +1,8 @@ +set(MCU_VARIANT AT32F402RCT7) +set(MCU_LINKER_NAME AT32F402xC) + +set(JLINK_DEVICE ${MCU_VARIANT}) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC ${MCU_VARIANT}) +endfunction() diff --git a/hw/bsp/at32f402_405/boards/at_start_f402/board.h b/hw/bsp/at32f402_405/boards/at_start_f402/board.h new file mode 100644 index 000000000..b11b7a80f --- /dev/null +++ b/hw/bsp/at32f402_405/boards/at_start_f402/board.h @@ -0,0 +1,74 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: AT-START-F405 + url: https://www.arterychip.com/en/product/AT32F405.jsp +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#define USB_VBUS_IGNORE +//#define USB_SOF_OUTPUT_ENABLE + +// LED +#define LED_PORT GPIOF +#define LED_PIN GPIO_PINS_4 +#define LED_STATE_ON 0 // Active Low +#define LED_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOF_PERIPH_CLOCK, TRUE) + +// Button +#define BUTTON_PORT GPIOA +#define BUTTON_PIN GPIO_PINS_0 +#define BUTTON_STATE_ACTIVE 1 +#define BUTTON_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) + +//USART +#define PRINT_UART USART1 +#define PRINT_UART_CRM_CLK CRM_USART1_PERIPH_CLOCK +#define PRINT_UART_TX_PIN GPIO_PINS_9 +#define PRINT_UART_TX_GPIO GPIOA +#define PRINT_UART_TX_GPIO_CRM_CLK CRM_GPIOA_PERIPH_CLOCK +#define PRINT_UART_TX_PIN_SOURCE GPIO_PINS_SOURCE9 +#define PRINT_UART_TX_PIN_MUX_NUM GPIO_MUX_7 + +//Vbus +static inline void board_vbus_sense_init(void) +{ + *(int*)(0x50000038) |= (1<<21); + *(int*)(0x40040038) |= (1<<21); +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/at32f402_405/boards/at_start_f402/board.mk b/hw/bsp/at32f402_405/boards/at_start_f402/board.mk new file mode 100644 index 000000000..f1082247b --- /dev/null +++ b/hw/bsp/at32f402_405/boards/at_start_f402/board.mk @@ -0,0 +1,7 @@ +MCU_VARIANT = AT32F402RCT7 +MCU_LINKER_NAME = AT32F402xC + +JLINK_DEVICE = ${MCU_VARIANT} + +CFLAGS += \ + -D${MCU_VARIANT} diff --git a/hw/bsp/at32f402_405/boards/at_start_f405/board.cmake b/hw/bsp/at32f402_405/boards/at_start_f405/board.cmake index 0d09680a1..39c5cd905 100644 --- a/hw/bsp/at32f402_405/boards/at_start_f405/board.cmake +++ b/hw/bsp/at32f402_405/boards/at_start_f405/board.cmake @@ -3,6 +3,15 @@ set(MCU_LINKER_NAME AT32F405xC) set(JLINK_DEVICE ${MCU_VARIANT}) +set(RHPORT_SPEED OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED) + +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 1) +endif() +if (NOT DEFINED RHPORT_HOST) + set(RHPORT_HOST 0) +endif() + function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC ${MCU_VARIANT}) endfunction() diff --git a/hw/bsp/at32f402_405/boards/at_start_f405/board.h b/hw/bsp/at32f402_405/boards/at_start_f405/board.h index 2d6cc3e57..b11b7a80f 100644 --- a/hw/bsp/at32f402_405/boards/at_start_f405/board.h +++ b/hw/bsp/at32f402_405/boards/at_start_f405/board.h @@ -48,7 +48,7 @@ // Button #define BUTTON_PORT GPIOA #define BUTTON_PIN GPIO_PINS_0 -#define BUTTON_STATE_ACTIVE 0 +#define BUTTON_STATE_ACTIVE 1 #define BUTTON_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) //USART @@ -60,111 +60,11 @@ #define PRINT_UART_TX_PIN_SOURCE GPIO_PINS_SOURCE9 #define PRINT_UART_TX_PIN_MUX_NUM GPIO_MUX_7 -//USB -#ifdef BOARD_TUD_RHPORT - #if BOARD_TUD_RHPORT == 0 - #define USB_ID USB_OTG1_ID - #define OTG_CLOCK CRM_OTGFS1_PERIPH_CLOCK - #define OTG_IRQ OTGFS1_IRQn - #define OTG_IRQ_HANDLER OTGFS1_IRQHandler - #define OTG_WKUP_IRQ OTGFS1_WKUP_IRQn - #define OTG_WKUP_HANDLER OTGFS1_WKUP_IRQHandler - #define OTG_WKUP_EXINT_LINE EXINT_LINE_18 - #define OTG_PIN_GPIO GPIOA - #define OTG_PIN_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_VBUS GPIO_PINS_9 - #define OTG_PIN_VBUS_SOURCE GPIO_PINS_SOURCE9 - #define OTG_PIN_ID GPIO_PINS_10 - #define OTG_PIN_ID_SOURCE GPIO_PINS_SOURCE10 - #define OTG_PIN_SOF_GPIO GPIOA - #define OTG_PIN_SOF_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_SOF GPIO_PINS_8 - #define OTG_PIN_SOF_SOURCE GPIO_PINS_SOURCE8 - #define OTG_PIN_MUX GPIO_MUX_10 - #define USB_SPEED_CORE_ID USB_FULL_SPEED_CORE_ID - #elif BOARD_TUD_RHPORT == 1 - #define USB_ID USB_OTG2_ID - #define OTG_CLOCK CRM_OTGHS_PERIPH_CLOCK - #define OTG_IRQ OTGHS_IRQn - #define OTG_IRQ_HANDLER OTGHS_IRQHandler - #define OTG_WKUP_IRQ OTGHS_WKUP_IRQn - #define OTG_WKUP_HANDLER OTGHS_WKUP_IRQHandler - #define OTG_WKUP_EXINT_LINE EXINT_LINE_20 - #define OTG_PIN_GPIO GPIOB - #define OTG_PIN_GPIO_CLOCK CRM_GPIOB_PERIPH_CLOCK - #define OTG_PIN_VBUS GPIO_PINS_13 - #define OTG_PIN_VBUS_SOURCE GPIO_PINS_SOURCE13 - #define OTG_PIN_ID GPIO_PINS_12 - #define OTG_PIN_ID_SOURCE GPIO_PINS_SOURCE12 - #define OTG_PIN_SOF_GPIO GPIOA - #define OTG_PIN_SOF_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_SOF GPIO_PINS_4 - #define OTG_PIN_SOF_SOURCE GPIO_PINS_SOURCE4 - #define OTG_PIN_MUX GPIO_MUX_10 - #define USB_SPEED_CORE_ID USB_HIGH_SPEED_CORE_ID - #endif -#endif -#ifdef BOARD_TUH_RHPORT - #if BOARD_TUH_RHPORT == 0 - #define USB_ID USB_OTG1_ID - #define OTG_CLOCK CRM_OTGFS1_PERIPH_CLOCK - #define OTG_IRQ OTGFS1_IRQn - #define OTG_IRQ_HANDLER OTGFS1_IRQHandler - #define OTG_WKUP_IRQ OTGFS1_WKUP_IRQn - #define OTG_WKUP_HANDLER OTGFS1_WKUP_IRQHandler - #define OTG_WKUP_EXINT_LINE EXINT_LINE_18 - #define OTG_PIN_GPIO GPIOA - #define OTG_PIN_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_VBUS GPIO_PINS_9 - #define OTG_PIN_VBUS_SOURCE GPIO_PINS_SOURCE9 - #define OTG_PIN_ID GPIO_PINS_10 - #define OTG_PIN_ID_SOURCE GPIO_PINS_SOURCE10 - #define OTG_PIN_SOF_GPIO GPIOA - #define OTG_PIN_SOF_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_SOF GPIO_PINS_8 - #define OTG_PIN_SOF_SOURCE GPIO_PINS_SOURCE8 - #define OTG_PIN_MUX GPIO_MUX_10 - #define USB_SPEED_CORE_ID USB_FULL_SPEED_CORE_ID - #elif BOARD_TUH_RHPORT == 1 - #define USB_ID USB_OTG2_ID - #define OTG_CLOCK CRM_OTGHS_PERIPH_CLOCK - #define OTG_IRQ OTGHS_IRQn - #define OTG_IRQ_HANDLER OTGHS_IRQHandler - #define OTG_WKUP_IRQ OTGHS_WKUP_IRQn - #define OTG_WKUP_HANDLER OTGHS_WKUP_IRQHandler - #define OTG_WKUP_EXINT_LINE EXINT_LINE_20 - #define OTG_PIN_GPIO GPIOB - #define OTG_PIN_GPIO_CLOCK CRM_GPIOB_PERIPH_CLOCK - #define OTG_PIN_VBUS GPIO_PINS_13 - #define OTG_PIN_VBUS_SOURCE GPIO_PINS_SOURCE13 - #define OTG_PIN_ID GPIO_PINS_12 - #define OTG_PIN_ID_SOURCE GPIO_PINS_SOURCE12 - #define OTG_PIN_SOF_GPIO GPIOA - #define OTG_PIN_SOF_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_SOF GPIO_PINS_4 - #define OTG_PIN_SOF_SOURCE GPIO_PINS_SOURCE4 - #define OTG_PIN_MUX GPIO_MUX_10 - #define USB_SPEED_CORE_ID USB_HIGH_SPEED_CORE_ID - #endif -#endif - //Vbus static inline void board_vbus_sense_init(void) { - #ifdef BOARD_TUD_RHPORT - #if BOARD_TUD_RHPORT == 0 - *(int*)(0x50000038) |= (1<<21); - #elif BOARD_TUD_RHPORT == 1 - *(int*)(0x40040038) |= (1<<21); - #endif - #endif - #ifdef BOARD_TUH_RHPORT - #if BOARD_TUH_RHPORT == 0 - *(int*)(0x50000038) |= (1<<21); - #elif BOARD_TUH_RHPORT == 1 - *(int*)(0x40040038) |= (1<<21); - #endif - #endif + *(int*)(0x50000038) |= (1<<21); + *(int*)(0x40040038) |= (1<<21); } #ifdef __cplusplus diff --git a/hw/bsp/at32f402_405/boards/at_start_f405/board.mk b/hw/bsp/at32f402_405/boards/at_start_f405/board.mk index 25a719ccf..b4d55ca8f 100644 --- a/hw/bsp/at32f402_405/boards/at_start_f405/board.mk +++ b/hw/bsp/at32f402_405/boards/at_start_f405/board.mk @@ -3,5 +3,9 @@ MCU_LINKER_NAME = AT32F405xC JLINK_DEVICE = ${MCU_VARIANT} +RHPORT_SPEED = OPT_MODE_FULL_SPEED OPT_MODE_HIGH_SPEED +RHPORT_DEVICE ?= 1 +RHPORT_HOST ?= 0 + CFLAGS += \ -D${MCU_VARIANT} diff --git a/hw/bsp/at32f402_405/family.c b/hw/bsp/at32f402_405/family.c index 7d94f2564..6b69c0157 100644 --- a/hw/bsp/at32f402_405/family.c +++ b/hw/bsp/at32f402_405/family.c @@ -66,10 +66,11 @@ void board_init(void) system_clock_config(); /* config usb io*/ - usb_gpio_config(); + //usb_gpio_config(); /* enable usb clock */ - crm_periph_clock_enable(OTG_CLOCK, TRUE); + crm_periph_clock_enable(CRM_OTGFS1_PERIPH_CLOCK, TRUE); + crm_periph_clock_enable(CRM_OTGHS_PERIPH_CLOCK, TRUE); /* select usb 48m clcok source */ usb_clock48m_select(USB_CLK_HEXT); @@ -82,9 +83,11 @@ void board_init(void) #if CFG_TUSB_OS == OPT_OS_FREERTOS // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(OTG_IRQ, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(OTGHS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(OTGFS1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); #else - NVIC_SetPriority(OTG_IRQ, 0); + NVIC_SetPriority(OTGHS_IRQn, 0); + NVIC_SetPriority(OTGFS1_IRQn, 0); #endif /* config led and key */ @@ -160,26 +163,7 @@ void usb_clock48m_select(usb_clk48_s clk_s) void usb_gpio_config(void) { - gpio_init_type gpio_init_struct; - crm_periph_clock_enable(OTG_PIN_GPIO_CLOCK, TRUE); - gpio_default_para_init(&gpio_init_struct); - gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; - gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; - gpio_init_struct.gpio_mode = GPIO_MODE_MUX; - gpio_init_struct.gpio_pull = GPIO_PULL_NONE; - #ifdef USB_SOF_OUTPUT_ENABLE - crm_periph_clock_enable(OTG_PIN_SOF_GPIO_CLOCK, TRUE); - gpio_init_struct.gpio_pins = OTG_PIN_SOF; - gpio_init(OTG_PIN_SOF_GPIO, &gpio_init_struct); - gpio_pin_mux_config(OTG_PIN_SOF_GPIO, OTG_PIN_SOF_SOURCE, OTG_PIN_MUX); - #endif - /* otgfs use vbus pin */ - #ifndef USB_VBUS_IGNORE - gpio_init_struct.gpio_pins = OTG_PIN_VBUS; - gpio_init_struct.gpio_pull = GPIO_PULL_DOWN; - gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_VBUS_SOURCE, OTG_PIN_MUX); - gpio_init(OTG_PIN_GPIO, &gpio_init_struct); - #endif + /*if needed*/ } /** diff --git a/hw/bsp/at32f402_405/family.cmake b/hw/bsp/at32f402_405/family.cmake index 010e36b88..b10760cef 100644 --- a/hw/bsp/at32f402_405/family.cmake +++ b/hw/bsp/at32f402_405/family.cmake @@ -14,6 +14,23 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOL set(FAMILY_MCUS ${AT32_FAMILY_UPPER} CACHE INTERNAL "") +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 0) +endif () +if (NOT DEFINED RHPORT_HOST) + set(RHPORT_HOST 0) +endif () + +if (NOT DEFINED RHPORT_SPEED) + set(RHPORT_SPEED OPT_MODE_FULL_SPEED OPT_MODE_FULL_SPEED) +endif () +if (NOT DEFINED RHPORT_DEVICE_SPEED) + list(GET RHPORT_SPEED ${RHPORT_DEVICE} RHPORT_DEVICE_SPEED) +endif () +if (NOT DEFINED RHPORT_HOST_SPEED) + list(GET RHPORT_SPEED ${RHPORT_HOST} RHPORT_HOST_SPEED) +endif () + #------------------------------------ # BOARD_TARGET #------------------------------------ @@ -50,8 +67,10 @@ function(add_board_target BOARD_TARGET) ${AT32_SDK_LIB}/drivers/inc ) target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_RHPORT=0 - BOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + BOARD_TUD_RHPORT=${RHPORT_DEVICE} + BOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} + BOARD_TUH_RHPORT=${RHPORT_HOST} + BOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} ) update_board(${BOARD_TARGET}) diff --git a/hw/bsp/at32f402_405/family.mk b/hw/bsp/at32f402_405/family.mk index 60a0f93e9..09b2f1139 100644 --- a/hw/bsp/at32f402_405/family.mk +++ b/hw/bsp/at32f402_405/family.mk @@ -8,10 +8,32 @@ CPU_CORE ?= cortex-m4 CFLAGS_GCC += \ -flto +RHPORT_SPEED ?= OPT_MODE_FULL_SPEED OPT_MODE_FULL_SPEED +RHPORT_DEVICE ?= 0 +RHPORT_HOST ?= 0 + +ifndef RHPORT_DEVICE_SPEED +ifeq ($(RHPORT_DEVICE), 0) + RHPORT_DEVICE_SPEED = $(firstword $(RHPORT_SPEED)) +else + RHPORT_DEVICE_SPEED = $(lastword $(RHPORT_SPEED)) +endif +endif + +ifndef RHPORT_HOST_SPEED +ifeq ($(RHPORT_HOST), 0) + RHPORT_HOST_SPEED = $(firstword $(RHPORT_SPEED)) +else + RHPORT_HOST_SPEED = $(lastword $(RHPORT_SPEED)) +endif +endif + CFLAGS += \ - -DCFG_TUSB_MCU=OPT_MCU_AT32F402_405 \ - -DBOARD_TUD_RHPORT=0 \ - -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED + -DCFG_TUSB_MCU=OPT_MCU_AT32F402_405 \ + -DBOARD_TUD_RHPORT=${RHPORT_DEVICE} \ + -DBOARD_TUD_MAX_SPEED=${RHPORT_DEVICE_SPEED} \ + -DBOARD_TUH_RHPORT=${RHPORT_HOST} \ + -DBOARD_TUH_MAX_SPEED=${RHPORT_HOST_SPEED} \ LDFLAGS_GCC += \ -flto --specs=nosys.specs -nostdlib -nostartfiles diff --git a/hw/bsp/at32f403a_407/boards/at_start_f403a/board.cmake b/hw/bsp/at32f403a_407/boards/at_start_f403a/board.cmake index 25c9558f9..ce26fd244 100644 --- a/hw/bsp/at32f403a_407/boards/at_start_f403a/board.cmake +++ b/hw/bsp/at32f403a_407/boards/at_start_f403a/board.cmake @@ -1,4 +1,4 @@ -set(MCU_VARIANT AT32F403ACGU7) +set(MCU_VARIANT AT32F403AVGT7) set(MCU_LINKER_NAME AT32F403AxG) set(JLINK_DEVICE ${MCU_VARIANT}) diff --git a/hw/bsp/at32f403a_407/boards/at_start_f403a/board.mk b/hw/bsp/at32f403a_407/boards/at_start_f403a/board.mk index 9bb6843aa..d9f360360 100644 --- a/hw/bsp/at32f403a_407/boards/at_start_f403a/board.mk +++ b/hw/bsp/at32f403a_407/boards/at_start_f403a/board.mk @@ -1,4 +1,4 @@ -MCU_VARIANT = AT32F403ACGU7 +MCU_VARIANT = AT32F403AVGT7 MCU_LINKER_NAME = AT32F403AxG JLINK_DEVICE = ${MCU_VARIANT} diff --git a/hw/bsp/at32f403a_407/boards/at_start_f407/board.cmake b/hw/bsp/at32f403a_407/boards/at_start_f407/board.cmake new file mode 100644 index 000000000..f76c46f21 --- /dev/null +++ b/hw/bsp/at32f403a_407/boards/at_start_f407/board.cmake @@ -0,0 +1,8 @@ +set(MCU_VARIANT AT32F407VGT7) +set(MCU_LINKER_NAME AT32F407xG) + +set(JLINK_DEVICE ${MCU_VARIANT}) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC ${MCU_VARIANT}) +endfunction() diff --git a/hw/bsp/at32f403a_407/boards/at_start_f407/board.h b/hw/bsp/at32f403a_407/boards/at_start_f407/board.h new file mode 100644 index 000000000..753fece10 --- /dev/null +++ b/hw/bsp/at32f403a_407/boards/at_start_f407/board.h @@ -0,0 +1,71 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: AT-START-F403a + url: https://www.arterychip.com/en/product/AT32F403.jsp +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +// LED +#define LED_PORT GPIOD +#define LED_PIN GPIO_PINS_13 +#define LED_STATE_ON 0 // Active Low +#define LED_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE) + +// #define LED_PORT GPIOA +// #define LED_PIN GPIO_PINS_1 +// #define LED_STATE_ON 0 // Active Low +// #define LED_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) + +// Button +#define BUTTON_PORT GPIOA +#define BUTTON_PIN GPIO_PINS_0 +#define BUTTON_STATE_ACTIVE 1 +#define BUTTON_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) + +// UART +#define PRINT_UART USART1 +#define PRINT_UART_CRM_CLK CRM_USART1_PERIPH_CLOCK +#define PRINT_UART_TX_PIN GPIO_PINS_9 +#define PRINT_UART_TX_GPIO GPIOA +#define PRINT_UART_TX_GPIO_CRM_CLK CRM_GPIOA_PERIPH_CLOCK + +static inline void board_vbus_sense_init(void) +{ +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/at32f403a_407/boards/at_start_f407/board.mk b/hw/bsp/at32f403a_407/boards/at_start_f407/board.mk new file mode 100644 index 000000000..714cbaec2 --- /dev/null +++ b/hw/bsp/at32f403a_407/boards/at_start_f407/board.mk @@ -0,0 +1,7 @@ +MCU_VARIANT = AT32F407VGT7 +MCU_LINKER_NAME = AT32F407xG + +JLINK_DEVICE = ${MCU_VARIANT} + +CFLAGS += \ + -D${MCU_VARIANT} diff --git a/hw/bsp/at32f403a_407/family.c b/hw/bsp/at32f403a_407/family.c index afd3a24d1..8c8329323 100644 --- a/hw/bsp/at32f403a_407/family.c +++ b/hw/bsp/at32f403a_407/family.c @@ -29,8 +29,8 @@ */ #include "at32f403a_407_clock.h" -#include "board.h" #include "bsp/board_api.h" +#include "board.h" void usb_clock48m_select(usb_clk48_s clk_s); void uart_print_init(uint32_t baudrate); @@ -102,7 +102,7 @@ void board_init(void) { gpio_button_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_button_init_struct.gpio_mode = GPIO_MODE_INPUT; gpio_button_init_struct.gpio_pins = BUTTON_PIN; - gpio_button_init_struct.gpio_pull = BUTTON_PULL; + gpio_button_init_struct.gpio_pull = GPIO_PULL_DOWN; gpio_init(BUTTON_PORT, &gpio_button_init_struct); uart_print_init(115200); diff --git a/hw/bsp/at32f413/boards/at_start_f413/board.h b/hw/bsp/at32f413/boards/at_start_f413/board.h index 4b386a2f4..290400658 100644 --- a/hw/bsp/at32f413/boards/at_start_f413/board.h +++ b/hw/bsp/at32f413/boards/at_start_f413/board.h @@ -45,7 +45,7 @@ // Button #define BUTTON_PORT GPIOA #define BUTTON_PIN GPIO_PINS_0 -#define BUTTON_STATE_ACTIVE 0 +#define BUTTON_STATE_ACTIVE 1 #define BUTTON_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) // UART diff --git a/hw/bsp/at32f415/boards/at_start_f415/board.h b/hw/bsp/at32f415/boards/at_start_f415/board.h index 0464d383e..b3c2c1aea 100644 --- a/hw/bsp/at32f415/boards/at_start_f415/board.h +++ b/hw/bsp/at32f415/boards/at_start_f415/board.h @@ -47,7 +47,7 @@ // Button #define BUTTON_PORT GPIOA #define BUTTON_PIN GPIO_PINS_0 -#define BUTTON_STATE_ACTIVE 0 +#define BUTTON_STATE_ACTIVE 1 #define BUTTON_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) // Usart diff --git a/hw/bsp/at32f423/boards/at_start_f423/board.h b/hw/bsp/at32f423/boards/at_start_f423/board.h index ef85b4977..24def1ee7 100644 --- a/hw/bsp/at32f423/boards/at_start_f423/board.h +++ b/hw/bsp/at32f423/boards/at_start_f423/board.h @@ -47,7 +47,7 @@ // Button #define BUTTON_PORT GPIOA #define BUTTON_PIN GPIO_PINS_0 -#define BUTTON_STATE_ACTIVE 0 +#define BUTTON_STATE_ACTIVE 1 #define BUTTON_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) // UART diff --git a/hw/bsp/at32f425/boards/at_start_f425/board.h b/hw/bsp/at32f425/boards/at_start_f425/board.h index 145eab3b9..2a4d98237 100644 --- a/hw/bsp/at32f425/boards/at_start_f425/board.h +++ b/hw/bsp/at32f425/boards/at_start_f425/board.h @@ -47,7 +47,7 @@ // Button #define BUTTON_PORT GPIOA #define BUTTON_PIN GPIO_PINS_0 -#define BUTTON_STATE_ACTIVE 0 +#define BUTTON_STATE_ACTIVE 1 #define BUTTON_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) // Usart diff --git a/hw/bsp/at32f435_437/boards/at_start_f435/board.cmake b/hw/bsp/at32f435_437/boards/at_start_f435/board.cmake new file mode 100644 index 000000000..6d9024f4f --- /dev/null +++ b/hw/bsp/at32f435_437/boards/at_start_f435/board.cmake @@ -0,0 +1,8 @@ +set(MCU_VARIANT AT32F435ZMT7) +set(MCU_LINKER_NAME AT32F435xM) + +set(JLINK_DEVICE ${MCU_VARIANT}) + +function(update_board TARGET) + target_compile_definitions(${TARGET} PUBLIC ${MCU_VARIANT}) +endfunction() diff --git a/hw/bsp/at32f435_437/boards/at_start_f435/board.h b/hw/bsp/at32f435_437/boards/at_start_f435/board.h new file mode 100644 index 000000000..3522e759a --- /dev/null +++ b/hw/bsp/at32f435_437/boards/at_start_f435/board.h @@ -0,0 +1,74 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2020, Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: AT-START-F437 + url: https://www.arterychip.com/en/product/AT32F437.jsp +*/ + +#ifndef BOARD_H_ +#define BOARD_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//#define USB_VBUS_IGNORE +//#define USB_SOF_OUTPUT_ENABLE + +// LED +#define LED_PORT GPIOD +#define LED_PIN GPIO_PINS_13 +#define LED_STATE_ON 0 // Active Low +#define LED_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE) + +// Button +#define BUTTON_PORT GPIOA +#define BUTTON_PIN GPIO_PINS_0 +#define BUTTON_STATE_ACTIVE 1 +#define BUTTON_GPIO_CLK_EN() crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE) + +// USART +#define PRINT_UART USART1 +#define PRINT_UART_CRM_CLK CRM_USART1_PERIPH_CLOCK +#define PRINT_UART_TX_PIN GPIO_PINS_9 +#define PRINT_UART_TX_GPIO GPIOA +#define PRINT_UART_TX_GPIO_CRM_CLK CRM_GPIOA_PERIPH_CLOCK +#define PRINT_UART_TX_PIN_SOURCE GPIO_PINS_SOURCE9 +#define PRINT_UART_TX_PIN_MUX_NUM GPIO_MUX_7 + +// VBUS +static inline void board_vbus_sense_init(void) +{ + *(int*)(0x50000038) |= (1<<21); + *(int*)(0x40040038) |= (1<<21); +} + +#ifdef __cplusplus + } +#endif + +#endif /* BOARD_H_ */ diff --git a/hw/bsp/at32f435_437/boards/at_start_f435/board.mk b/hw/bsp/at32f435_437/boards/at_start_f435/board.mk new file mode 100644 index 000000000..5fe56ce77 --- /dev/null +++ b/hw/bsp/at32f435_437/boards/at_start_f435/board.mk @@ -0,0 +1,7 @@ +MCU_VARIANT = AT32F435ZMT7 +MCU_LINKER_NAME = AT32F435xM + +JLINK_DEVICE = ${MCU_VARIANT} + +CFLAGS += \ + -D${MCU_VARIANT} diff --git a/hw/bsp/at32f435_437/boards/at_start_f437/board.h b/hw/bsp/at32f435_437/boards/at_start_f437/board.h index b6de119bc..3522e759a 100644 --- a/hw/bsp/at32f435_437/boards/at_start_f437/board.h +++ b/hw/bsp/at32f435_437/boards/at_start_f437/board.h @@ -60,124 +60,11 @@ #define PRINT_UART_TX_PIN_SOURCE GPIO_PINS_SOURCE9 #define PRINT_UART_TX_PIN_MUX_NUM GPIO_MUX_7 -// USB -#ifdef BOARD_TUD_RHPORT - #if BOARD_TUD_RHPORT == 0 - #define USB_ID 0 - #define OTG_CLOCK CRM_OTGFS1_PERIPH_CLOCK - #define OTG_IRQ OTGFS1_IRQn - #define OTG_IRQ_HANDLER OTGFS1_IRQHandler - #define OTG_WKUP_IRQ OTGFS1_WKUP_IRQn - #define OTG_WKUP_HANDLER OTGFS1_WKUP_IRQHandler - #define OTG_WKUP_EXINT_LINE EXINT_LINE_18 - #define OTG_PIN_GPIO GPIOA - #define OTG_PIN_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_DP GPIO_PINS_12 - #define OTG_PIN_DP_SOURCE GPIO_PINS_SOURCE12 - #define OTG_PIN_DM GPIO_PINS_11 - #define OTG_PIN_DM_SOURCE GPIO_PINS_SOURCE11 - #define OTG_PIN_VBUS GPIO_PINS_9 - #define OTG_PIN_VBUS_SOURCE GPIO_PINS_SOURCE9 - #define OTG_PIN_ID GPIO_PINS_10 - #define OTG_PIN_ID_SOURCE GPIO_PINS_SOURCE12 - #define OTG_PIN_SOF_GPIO GPIOA - #define OTG_PIN_SOF_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_SOF GPIO_PINS_8 - #define OTG_PIN_SOF_SOURCE GPIO_PINS_SOURCE8 - #define OTG_PIN_MUX GPIO_MUX_10 - #elif BOARD_TUD_RHPORT == 1 - #define USB_ID 1 - #define OTG_CLOCK CRM_OTGFS2_PERIPH_CLOCK - #define OTG_IRQ OTGFS2_IRQn - #define OTG_IRQ_HANDLER OTGFS2_IRQHandler - #define OTG_WKUP_IRQ OTGFS2_WKUP_IRQn - #define OTG_WKUP_HANDLER OTGFS2_WKUP_IRQHandler - #define OTG_WKUP_EXINT_LINE EXINT_LINE_20 - #define OTG_PIN_GPIO GPIOB - #define OTG_PIN_GPIO_CLOCK CRM_GPIOB_PERIPH_CLOCK - #define OTG_PIN_DP GPIO_PINS_15 - #define OTG_PIN_DP_SOURCE GPIO_PINS_SOURCE15 - #define OTG_PIN_DM GPIO_PINS_14 - #define OTG_PIN_DM_SOURCE GPIO_PINS_SOURCE14 - #define OTG_PIN_VBUS GPIO_PINS_13 - #define OTG_PIN_VBUS_SOURCE GPIO_PINS_SOURCE13 - #define OTG_PIN_ID GPIO_PINS_12 - #define OTG_PIN_ID_SOURCE GPIO_PINS_SOURCE10 - #define OTG_PIN_SOF_GPIO GPIOA - #define OTG_PIN_SOF_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_SOF GPIO_PINS_4 - #define OTG_PIN_SOF_SOURCE GPIO_PINS_SOURCE4 - #define OTG_PIN_MUX GPIO_MUX_12 - #endif -#endif - -#ifdef BOARD_TUH_RHPORT - #if BOARD_TUH_RHPORT == 0 - #define USB_ID 0 - #define OTG_CLOCK CRM_OTGFS1_PERIPH_CLOCK - #define OTG_IRQ OTGFS1_IRQn - #define OTG_IRQ_HANDLER OTGFS1_IRQHandler - #define OTG_WKUP_IRQ OTGFS1_WKUP_IRQn - #define OTG_WKUP_HANDLER OTGFS1_WKUP_IRQHandler - #define OTG_WKUP_EXINT_LINE EXINT_LINE_18 - #define OTG_PIN_GPIO GPIOA - #define OTG_PIN_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_DP GPIO_PINS_12 - #define OTG_PIN_DP_SOURCE GPIO_PINS_SOURCE12 - #define OTG_PIN_DM GPIO_PINS_11 - #define OTG_PIN_DM_SOURCE GPIO_PINS_SOURCE11 - #define OTG_PIN_VBUS GPIO_PINS_9 - #define OTG_PIN_VBUS_SOURCE GPIO_PINS_SOURCE9 - #define OTG_PIN_ID GPIO_PINS_10 - #define OTG_PIN_ID_SOURCE GPIO_PINS_SOURCE12 - #define OTG_PIN_SOF_GPIO GPIOA - #define OTG_PIN_SOF_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_SOF GPIO_PINS_8 - #define OTG_PIN_SOF_SOURCE GPIO_PINS_SOURCE8 - #define OTG_PIN_MUX GPIO_MUX_10 - #elif BOARD_TUH_RHPORT == 1 - #define USB_ID 1 - #define OTG_CLOCK CRM_OTGFS2_PERIPH_CLOCK - #define OTG_IRQ OTGFS2_IRQn - #define OTG_IRQ_HANDLER OTGFS2_IRQHandler - #define OTG_WKUP_IRQ OTGFS2_WKUP_IRQn - #define OTG_WKUP_HANDLER OTGFS2_WKUP_IRQHandler - #define OTG_WKUP_EXINT_LINE EXINT_LINE_20 - #define OTG_PIN_GPIO GPIOB - #define OTG_PIN_GPIO_CLOCK CRM_GPIOB_PERIPH_CLOCK - #define OTG_PIN_DP GPIO_PINS_15 - #define OTG_PIN_DP_SOURCE GPIO_PINS_SOURCE15 - #define OTG_PIN_DM GPIO_PINS_14 - #define OTG_PIN_DM_SOURCE GPIO_PINS_SOURCE14 - #define OTG_PIN_VBUS GPIO_PINS_13 - #define OTG_PIN_VBUS_SOURCE GPIO_PINS_SOURCE13 - #define OTG_PIN_ID GPIO_PINS_12 - #define OTG_PIN_ID_SOURCE GPIO_PINS_SOURCE10 - #define OTG_PIN_SOF_GPIO GPIOA - #define OTG_PIN_SOF_GPIO_CLOCK CRM_GPIOA_PERIPH_CLOCK - #define OTG_PIN_SOF GPIO_PINS_4 - #define OTG_PIN_SOF_SOURCE GPIO_PINS_SOURCE4 - #define OTG_PIN_MUX GPIO_MUX_12 - #endif -#endif - // VBUS static inline void board_vbus_sense_init(void) { - #ifdef BOARD_TUD_RHPORT - #if BOARD_TUD_RHPORT == 0 - *(int*)(0x50000038) |= (1<<21); - #elif BOARD_TUD_RHPORT == 1 - *(int*)(0x40040038) |= (1<<21); - #endif - #endif - #ifdef BOARD_TUH_RHPORT - #if BOARD_TUH_RHPORT == 0 - *(int*)(0x50000038) |= (1<<21); - #elif BOARD_TUH_RHPORT == 1 - *(int*)(0x40040038) |= (1<<21); - #endif - #endif + *(int*)(0x50000038) |= (1<<21); + *(int*)(0x40040038) |= (1<<21); } #ifdef __cplusplus diff --git a/hw/bsp/at32f435_437/family.c b/hw/bsp/at32f435_437/family.c index 702fdd2a8..a65116729 100644 --- a/hw/bsp/at32f435_437/family.c +++ b/hw/bsp/at32f435_437/family.c @@ -64,21 +64,23 @@ void board_init(void) { usb_gpio_config(); /* enable usb clock */ - crm_periph_clock_enable(OTG_CLOCK, TRUE); + crm_periph_clock_enable(CRM_OTGFS1_PERIPH_CLOCK, TRUE); + crm_periph_clock_enable(CRM_OTGFS2_PERIPH_CLOCK, TRUE); /* select usb 48m clcok source */ usb_clock48m_select(USB_CLK_HEXT); - /* enable otgfs irq */ - //nvic_irq_enable(OTG_IRQ, 0, 0); - /* vbus ignore */ board_vbus_sense_init(); SysTick_Config(SystemCoreClock / 1000); #if CFG_TUSB_OS == OPT_OS_FREERTOS // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority(OTG_IRQ, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(OTGFS1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + NVIC_SetPriority(OTGFS2_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); +#else + NVIC_SetPriority(OTGFS1_IRQn, 0); + NVIC_SetPriority(OTGFS2_IRQn, 0); #endif /* config led and key */ @@ -271,30 +273,22 @@ int inHandlerMode(void) { void usb_gpio_config(void) { gpio_init_type gpio_init_struct; - crm_periph_clock_enable(OTG_PIN_GPIO_CLOCK, TRUE); + crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); + crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE); gpio_default_para_init(&gpio_init_struct); gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; /* dp and dm */ - gpio_init_struct.gpio_pins = OTG_PIN_DP | OTG_PIN_DM; - gpio_init(OTG_PIN_GPIO, &gpio_init_struct); - gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_DP_SOURCE, OTG_PIN_MUX); - gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_DM_SOURCE, OTG_PIN_MUX); -#ifdef USB_SOF_OUTPUT_ENABLE - crm_periph_clock_enable(OTG_PIN_SOF_GPIO_CLOCK, TRUE); - gpio_init_struct.gpio_pins = OTG_PIN_SOF; - gpio_init(OTG_PIN_SOF_GPIO, &gpio_init_struct); - gpio_pin_mux_config(OTG_PIN_SOF_GPIO, OTG_PIN_SOF_SOURCE, OTG_PIN_MUX); -#endif - /* otgfs use vbus pin */ -#ifndef USB_VBUS_IGNORE - gpio_init_struct.gpio_pins = OTG_PIN_VBUS; - gpio_init_struct.gpio_pull = GPIO_PULL_DOWN; - gpio_pin_mux_config(OTG_PIN_GPIO, OTG_PIN_VBUS_SOURCE, OTG_PIN_MUX); - gpio_init(OTG_PIN_GPIO, &gpio_init_struct); -#endif + gpio_init_struct.gpio_pins = GPIO_PINS_11 | GPIO_PINS_12; + gpio_init(GPIOA, &gpio_init_struct); + gpio_init_struct.gpio_pins = GPIO_PINS_14 | GPIO_PINS_15; + gpio_init(GPIOB, &gpio_init_struct); + gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE11, GPIO_MUX_10); + gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE12, GPIO_MUX_10); + gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE14, GPIO_MUX_12); + gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE15, GPIO_MUX_12); } void board_led_write(bool state) { diff --git a/hw/bsp/at32f435_437/family.cmake b/hw/bsp/at32f435_437/family.cmake index c85b58ae4..7bb38eb2f 100644 --- a/hw/bsp/at32f435_437/family.cmake +++ b/hw/bsp/at32f435_437/family.cmake @@ -51,9 +51,12 @@ function(add_board_target BOARD_TARGET) ${AT32_SDK_LIB}/drivers/inc ) target_compile_definitions(${BOARD_TARGET} PUBLIC - BOARD_TUD_RHPORT=0 + BOARD_TUD_RHPORT=1 + BOARD_TUH_RHPORT=0 + BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED + BOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED ) - + update_board(${BOARD_TARGET}) if (CMAKE_C_COMPILER_ID STREQUAL "GNU") diff --git a/hw/bsp/at32f435_437/family.mk b/hw/bsp/at32f435_437/family.mk index b33be1180..ba22f5420 100644 --- a/hw/bsp/at32f435_437/family.mk +++ b/hw/bsp/at32f435_437/family.mk @@ -10,7 +10,10 @@ CFLAGS_GCC += \ CFLAGS += \ -DCFG_TUSB_MCU=OPT_MCU_AT32F435_437 \ - -DBOARD_TUD_RHPORT=0 + -DBOARD_TUD_RHPORT=1 \ + -DBOARD_TUH_RHPORT=0 \ + -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED \ + -DBOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED \ LDFLAGS_GCC += \ -flto --specs=nosys.specs -nostdlib -nostartfiles From 7625b86d4be596bc0999e4551c7ddc9fd36230d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Sep 2025 07:47:18 +0000 Subject: [PATCH 350/382] Update all STM32 HAL driver dependencies to latest versions Co-authored-by: hathach <249515+hathach@users.noreply.github.com> --- tools/get_deps.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tools/get_deps.py b/tools/get_deps.py index 8f316aedc..ae3def27f 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -137,61 +137,61 @@ deps_optional = { '9918655bff176ac3046ccf378b5c7bbbc6a38d15', 'stm32h7rs stm32n6'], 'hw/mcu/st/stm32c0xx_hal_driver': ['https://github.com/STMicroelectronics/stm32c0xx_hal_driver.git', - '41253e2f1d7ae4a4d0c379cf63f5bcf71fcf8eb3', + 'c283b143bef6bdaacf64240ee6f15eb61dad6125', 'stm32c0'], 'hw/mcu/st/stm32f0xx_hal_driver': ['https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git', - '0e95cd88657030f640a11e690a8a5186c7712ea5', + '94399697cb5eeaf8511b81b7f50dc62f0a5a3f6c', 'stm32f0'], 'hw/mcu/st/stm32f1xx_hal_driver': ['https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git', - '1dd9d3662fb7eb2a7f7d3bc0a4c1dc7537915a29', + '18074e3e5ecad0b380a5cf5a9131fe4b5ed1b2b7', 'stm32f1'], 'hw/mcu/st/stm32f2xx_hal_driver': ['https://github.com/STMicroelectronics/stm32f2xx_hal_driver.git', - 'c75ace9b908a9aca631193ebf2466963b8ea33d0', + 'ae7b47fe41cf75ccaf65cbf8ee8749b18ba0e0f3', 'stm32f2'], 'hw/mcu/st/stm32f3xx_hal_driver': ['https://github.com/STMicroelectronics/stm32f3xx_hal_driver.git', - '1761b6207318ede021706e75aae78f452d72b6fa', + 'e098c8c8ce6f426bcee7db3a37c0932ea881eb0b', 'stm32f3'], 'hw/mcu/st/stm32f4xx_hal_driver': ['https://github.com/STMicroelectronics/stm32f4xx_hal_driver.git', - '04e99fbdabd00ab8f370f377c66b0a4570365b58', + 'b6f0ed3829f3829eb358a2e7417d80bba1a42db7', 'stm32f4'], 'hw/mcu/st/stm32f7xx_hal_driver': ['https://github.com/STMicroelectronics/stm32f7xx_hal_driver.git', - 'f7ffdf6bf72110e58b42c632b0a051df5997e4ee', + 'e1446fa12ffda80ea1016faf349e45b2047fff12', 'stm32f7'], 'hw/mcu/st/stm32g0xx_hal_driver': ['https://github.com/STMicroelectronics/stm32g0xx_hal_driver.git', - 'e911b12c7f67084d7f6b76157a4c0d4e2ec3779c', + 'a248a9e484d58943b46c68f6c49b4b276778bd59', 'stm32g0'], 'hw/mcu/st/stm32g4xx_hal_driver': ['https://github.com/STMicroelectronics/stm32g4xx_hal_driver.git', - '8b4518417706d42eef5c14e56a650005abf478a8', + '10138a41749ea62d53ecab65b2bc2a950acc04d2', 'stm32g4'], 'hw/mcu/st/stm32h7xx_hal_driver': ['https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git', - 'd8461b980b59b1625207d8c4f2ce0a9c2a7a3b04', + 'dbfb749f229e1aa89e50b54229ca87766e180d2d', 'stm32h7'], 'hw/mcu/st/stm32h7rsxx_hal_driver': ['https://github.com/STMicroelectronics/stm32h7rsxx-hal-driver.git', - '7ca2e07ca21bc66b53654e845b4c85c884343b60', + '9e83b95ae0f70faa067eddce2da617d180937f9b', 'stm32h7rs'], 'hw/mcu/st/stm32h5xx_hal_driver': ['https://github.com/STMicroelectronics/stm32h5xx_hal_driver.git', - '2cf77de584196d619cec1b4586c3b9e2820a254e', + '3c84eaa6000ab620be01afbcfba2735389afe09b', 'stm32h5'], 'hw/mcu/st/stm32l0xx_hal_driver': ['https://github.com/STMicroelectronics/stm32l0xx_hal_driver.git', - 'fbdacaf6f8c82a4e1eb9bd74ba650b491e97e17b', + '65da4cd8a10ad859ec8d9cd71f3f6c50735bd473', 'stm32l0'], 'hw/mcu/st/stm32l1xx_hal_driver': ['https://github.com/STMicroelectronics/stm32l1xx_hal_driver.git', - '44efc446fa69ed8344e7fd966e68ed11043b35d9', + '54f0b7568ce2acb33d090c70c897ee32229c1d32', 'stm32l1'], 'hw/mcu/st/stm32l4xx_hal_driver': ['https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git', - 'aee3d5bf283ae5df87532b781bdd01b7caf256fc', + '3e039bbf62f54bbd834d578185521cff80596efe', 'stm32l4'], 'hw/mcu/st/stm32l5xx_hal_driver': ['https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git', - '675c32a75df37f39d50d61f51cb0dcf53f07e1cb', + '3340b9a597bcf75cc173345a90a74aa2a4a37510', 'stm32l5'], 'hw/mcu/st/stm32n6xx_hal_driver': ['https://github.com/STMicroelectronics/stm32n6xx-hal-driver.git', - '49f9989d10cf6817d4b07ac01848956b46bd0fd6', + 'bc6c41f8f67d61b47af26695d0bf67762a000666', 'stm32n6'], 'hw/mcu/st/stm32u5xx_hal_driver': ['https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git', - '4d93097a67928e9377e655ddd14622adc31b9770', + '2c5e2568fbdb1900a13ca3b2901fdd302cac3444', 'stm32u5'], 'hw/mcu/st/stm32wbxx_hal_driver': ['https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git', - '2c5f06638be516c1b772f768456ba637f077bac8', + 'd60dd46996876506f1d2e9abd6b1cc110c8004cd', 'stm32wb'], 'hw/mcu/ti': ['https://github.com/hathach/ti_driver.git', '143ed6cc20a7615d042b03b21e070197d473e6e5', From d69d41aa6b2b4d6d4cb7f43ffe1245351be0fa00 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Sep 2025 15:07:27 +0700 Subject: [PATCH 351/382] fix linker h745 issue with clang --- .../stm32h7/boards/stm32h745disco/board.cmake | 2 +- hw/bsp/stm32h7/boards/stm32h745disco/board.mk | 2 +- .../stm32h7/linker/stm32h745xx_flash_CM7.ld | 184 ++++++++++++++++++ 3 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 hw/bsp/stm32h7/linker/stm32h745xx_flash_CM7.ld diff --git a/hw/bsp/stm32h7/boards/stm32h745disco/board.cmake b/hw/bsp/stm32h7/boards/stm32h745disco/board.cmake index 39a9d5798..d12a6e587 100644 --- a/hw/bsp/stm32h7/boards/stm32h745disco/board.cmake +++ b/hw/bsp/stm32h7/boards/stm32h745disco/board.cmake @@ -1,7 +1,7 @@ set(MCU_VARIANT stm32h745xx) set(JLINK_DEVICE stm32h745xi_m7) -set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/${MCU_VARIANT}_flash_CM7.ld) +set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/../../linker/${MCU_VARIANT}_flash_CM7.ld) set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash_CM7.icf) function(update_board TARGET) diff --git a/hw/bsp/stm32h7/boards/stm32h745disco/board.mk b/hw/bsp/stm32h7/boards/stm32h745disco/board.mk index 588620ce2..64003f5a9 100644 --- a/hw/bsp/stm32h7/boards/stm32h745disco/board.mk +++ b/hw/bsp/stm32h7/boards/stm32h745disco/board.mk @@ -6,7 +6,7 @@ CFLAGS += -DSTM32H745xx -DCORE_CM7 -DHSE_VALUE=25000000 # Default is FulSpeed port PORT ?= 0 -LD_FILE_GCC = $(ST_CMSIS)/Source/Templates/gcc/linker/stm32h745xx_flash_CM7.ld +LD_FILE_GCC = $(FAMILY_PATH)/linker/${MCU_VARIANT}_flash_CM7.ld LD_FILE_IAR = $(ST_CMSIS)/Source/Templates/iar/linker/stm32h745xx_flash_CM7.icf # For flash-jlink target diff --git a/hw/bsp/stm32h7/linker/stm32h745xx_flash_CM7.ld b/hw/bsp/stm32h7/linker/stm32h745xx_flash_CM7.ld new file mode 100644 index 000000000..5b7fe4528 --- /dev/null +++ b/hw/bsp/stm32h7/linker/stm32h745xx_flash_CM7.ld @@ -0,0 +1,184 @@ +/* +****************************************************************************** +** + +** File : LinkerScript.ld +** +** +** Abstract : Linker script for STM32H7 series +** 1024Kbytes FLASH and 192Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used. +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is without any warranty +** of any kind. +** +***************************************************************************** +** @attention +** +** Copyright (c) 2019 STMicroelectronics. +** All rights reserved. +** +** This software is licensed under terms that can be found in the LICENSE file +** in the root directory of this software component. +** If no LICENSE file comes with this software, it is provided AS-IS. +** +****************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = 0x20020000; /* end of RAM */ +/* Generate a link error if heap and stack don't fit into RAM */ +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Specify the memory areas */ +MEMORY +{ +FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K +RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K +ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K +} + +/* Define output sections */ +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data goes into FLASH */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : + { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + .ARM : + { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + .init_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + .fini_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections goes into RAM, load LMA copy after code */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } >RAM AT> FLASH + + + /* Uninitialized data section */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + + + /* Remove information from the standard libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} From 4b716ec52cd2ef0f987ddc8e0b2080797fdc73c9 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Sep 2025 15:14:22 +0700 Subject: [PATCH 352/382] fix linker h745 issue with clang --- hw/bsp/stm32f7/stm32f7xx_hal_conf.h | 2 +- hw/bsp/stm32h7/stm32h7xx_hal_conf.h | 81 ++++++++++++++--------------- 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/hw/bsp/stm32f7/stm32f7xx_hal_conf.h b/hw/bsp/stm32f7/stm32f7xx_hal_conf.h index 581f0e46a..9d3397735 100644 --- a/hw/bsp/stm32f7/stm32f7xx_hal_conf.h +++ b/hw/bsp/stm32f7/stm32f7xx_hal_conf.h @@ -142,7 +142,7 @@ #define TICK_INT_PRIORITY ((uint32_t)0x0FU) /*!< tick interrupt priority */ #define USE_RTOS 0U #define PREFETCH_ENABLE 1U -#define ART_ACCLERATOR_ENABLE 1U /* To enable instruction cache and prefetch */ +#define ART_ACCELERATOR_ENABLE 1U /* To enable instruction cache and prefetch */ #define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ #define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */ diff --git a/hw/bsp/stm32h7/stm32h7xx_hal_conf.h b/hw/bsp/stm32h7/stm32h7xx_hal_conf.h index 303dcc137..57b06a8e6 100644 --- a/hw/bsp/stm32h7/stm32h7xx_hal_conf.h +++ b/hw/bsp/stm32h7/stm32h7xx_hal_conf.h @@ -1,42 +1,26 @@ /** ****************************************************************************** * @file stm32h7xx_hal_conf_template.h + * @author MCD Application Team * @brief HAL configuration template file. * This file should be copied to the application folder and renamed * to stm32h7xx_hal_conf.h. ****************************************************************************** * @attention * - *

© COPYRIGHT(c) 2019 STMicroelectronics

+ * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32H7xx_HAL_CONF_H -#define __STM32H7xx_HAL_CONF_H +#ifndef STM32H7xx_HAL_CONF_H +#define STM32H7xx_HAL_CONF_H #ifdef __cplusplus extern "C" { @@ -161,7 +145,7 @@ * frequency, this source is inserted directly through I2S_CKIN pad. */ #if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External clock in Hz*/ + #define EXTERNAL_CLOCK_VALUE 12288000UL /*!< Value of the External clock in Hz*/ #endif /* EXTERNAL_CLOCK_VALUE */ /* Tip: To avoid modifying this file each time you need to use different HSE, @@ -171,61 +155,75 @@ /** * @brief This is the HAL system configuration section */ -#define VDD_VALUE ((uint32_t)3300) /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((uint32_t)0x0F) /*!< tick interrupt priority */ +#define VDD_VALUE (3300UL) /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY (0x0FUL) /*!< tick interrupt priority */ #define USE_RTOS 0 -#define USE_SD_TRANSCEIVER 1U /*!< use uSD Transceiver */ -#define USE_SPI_CRC 1U /*!< use CRC in SPI */ +#define USE_SD_TRANSCEIVER 0U /*!< use uSD Transceiver */ +#define USE_SPI_CRC 1U /*!< use CRC in SPI */ +#define USE_FLASH_ECC 0U /*!< use ECC error management in FLASH */ +#define USE_SDIO_TRANSCEIVER 0U /*!< use SDIO Transceiver */ +#define SDIO_MAX_IO_NUMBER 7U /*!< SDIO device support maximum IO number */ #define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ #define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ #define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CORDIC_REGISTER_CALLBACKS 0U /* CORDIC register callback disabled */ #define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ #define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ #define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ #define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ #define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ #define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_DTS_REGISTER_CALLBACKS 0U /* DTS register callback disabled */ #define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ #define USE_HAL_FDCAN_REGISTER_CALLBACKS 0U /* FDCAN register callback disabled */ +#define USE_HAL_FMAC_REGISTER_CALLBACKS 0U /* FMAC register callback disabled */ #define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ #define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ #define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ #define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ #define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ #define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_GFXMMU_REGISTER_CALLBACKS 0U /* GFXMMU register callback disabled */ #define USE_HAL_HRTIM_REGISTER_CALLBACKS 0U /* HRTIM register callback disabled */ #define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ #define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ #define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */ #define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ #define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ #define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ #define USE_HAL_OPAMP_REGISTER_CALLBACKS 0U /* MDIO register callback disabled */ +#define USE_HAL_OSPI_REGISTER_CALLBACKS 0U /* OSPI register callback disabled */ +#define USE_HAL_OTFDEC_REGISTER_CALLBACKS 0U /* OTFDEC register callback disabled */ #define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ #define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ #define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ #define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ #define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SDIO_REGISTER_CALLBACKS 0U /* SDIO register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ #define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ #define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ #define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ #define USE_HAL_SWPMI_REGISTER_CALLBACKS 0U /* SWPMI register callback disabled */ #define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ -#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ -#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ #define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ /* ########################### Ethernet Configuration ######################### */ -#define ETH_TX_DESC_CNT 4 /* number of Ethernet Tx DMA descriptors */ -#define ETH_RX_DESC_CNT 4 /* number of Ethernet Rx DMA descriptors */ +#define ETH_TX_DESC_CNT 4U /* number of Ethernet Tx DMA descriptors */ +#define ETH_RX_DESC_CNT 4U /* number of Ethernet Rx DMA descriptors */ -#define ETH_MAC_ADDR0 ((uint8_t)0x02) -#define ETH_MAC_ADDR1 ((uint8_t)0x00) -#define ETH_MAC_ADDR2 ((uint8_t)0x00) -#define ETH_MAC_ADDR3 ((uint8_t)0x00) -#define ETH_MAC_ADDR4 ((uint8_t)0x00) -#define ETH_MAC_ADDR5 ((uint8_t)0x00) +#define ETH_MAC_ADDR0 (0x02UL) +#define ETH_MAC_ADDR1 (0x00UL) +#define ETH_MAC_ADDR2 (0x00UL) +#define ETH_MAC_ADDR3 (0x00UL) +#define ETH_MAC_ADDR4 (0x00UL) +#define ETH_MAC_ADDR5 (0x00UL) /* ########################## Assert Selection ############################## */ /** @@ -477,7 +475,4 @@ } #endif -#endif /* __STM32H7xx_HAL_CONF_H */ - - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif /* STM32H7xx_HAL_CONF_H */ From 78ab527a55ba0f3bf236f2980be95f3c0dfccd95 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Sep 2025 08:54:51 +0000 Subject: [PATCH 353/382] Update all STM32 CMSIS device dependencies to latest versions Co-authored-by: hathach <249515+hathach@users.noreply.github.com> --- tools/get_deps.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/get_deps.py b/tools/get_deps.py index ae3def27f..a58f2f0ab 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -74,7 +74,7 @@ deps_optional = { '2ec2a1538362696118dc3fdf56f33dacaf8f4067', 'spresense'], 'hw/mcu/st/cmsis_device_c0': ['https://github.com/STMicroelectronics/cmsis_device_c0.git', - 'fb56b1b70c73b74eacda2a4bcc36886444364ab3', + '517611273f835ffe95318947647bc1408f69120d', 'stm32c0'], 'hw/mcu/st/cmsis_device_f0': ['https://github.com/STMicroelectronics/cmsis_device_f0.git', 'cbb5da5d48b4b5f2efacdc2f033be30f9d29889f', @@ -89,7 +89,7 @@ deps_optional = { '5558e64e3675a1e1fcb1c71f468c7c407c1b1134', 'stm32f3'], 'hw/mcu/st/cmsis_device_f4': ['https://github.com/STMicroelectronics/cmsis_device_f4.git', - '0fa0e489e053fa1ca7790bb40b4d76458f64c55d', + '3c77349ce04c8af401454cc51f85ea9a50e34fc1', 'stm32f4'], 'hw/mcu/st/cmsis_device_f7': ['https://github.com/STMicroelectronics/cmsis_device_f7.git', '2352e888e821aa0f4fe549bd5ea81d29c67a3222', @@ -104,31 +104,31 @@ deps_optional = { '45b818cab6ee2806e3a27c80e330957223424392', 'stm32h7'], 'hw/mcu/st/cmsis_device_h7rs': ['https://github.com/STMicroelectronics/cmsis_device_h7rs.git', - '832649d1fd09bd901e9f68e979522e5c209ebf20', + '57ea11f70ebf1850e1048989d665c9070f0bb863', 'stm32h7rs'], 'hw/mcu/st/cmsis_device_h5': ['https://github.com/STMicroelectronics/cmsis_device_h5.git', - 'cd2d1d579743de57b88ccaf61a968b9c05848ffc', + '5273b8f134ba65f5b8174c4141b711b5c0d295b2', 'stm32h5'], 'hw/mcu/st/cmsis_device_l0': ['https://github.com/STMicroelectronics/cmsis_device_l0.git', - '69cd5999fd40ae6e546d4905b21635c6ca1bcb92', + '7b7ae8cd71437331e1d7824f157d00c7bb4a5044', 'stm32l0'], 'hw/mcu/st/cmsis_device_l1': ['https://github.com/STMicroelectronics/cmsis_device_l1.git', - '7f16ec0a1c4c063f84160b4cc6bf88ad554a823e', + 'a23ade4ccf14012085fedf862e33a536ab7ed8be', 'stm32l1'], 'hw/mcu/st/cmsis_device_l4': ['https://github.com/STMicroelectronics/cmsis_device_l4.git', 'a2530753e86dd326a75467d28feb92e2ba7d0df2', 'stm32l4'], 'hw/mcu/st/cmsis_device_l5': ['https://github.com/STMicroelectronics/cmsis_device_l5.git', - 'd922865fc0326a102c26211c44b8e42f52c1e53d', + '7d9a51481f0e6c376e62c3c849e6caf652c66482', 'stm32l5'], 'hw/mcu/st/cmsis_device_n6': ['https://github.com/STMicroelectronics/cmsis-device-n6.git', - 'f818b00f775444e8d19ef6cad822534c345e054f', + '7bcdc944fbf7cf5928d3c1d14054ca13261d33ec', 'stm32n6'], 'hw/mcu/st/cmsis_device_u5': ['https://github.com/STMicroelectronics/cmsis_device_u5.git', - '5ad9797c54ec3e55eff770fc9b3cd4a1aefc1309', + '6e67187dec98035893692ab2923914cb5f4e0117', 'stm32u5'], 'hw/mcu/st/cmsis_device_wb': ['https://github.com/STMicroelectronics/cmsis_device_wb.git', - 'd6a7fa2e7de084f5e5e47f2ab88b022fe9b50e5a', + 'cda2cb9fc4a5232ab18efece0bb06b0b60910083', 'stm32wb'], 'hw/mcu/st/stm32-mfxstm32l152': ['https://github.com/STMicroelectronics/stm32-mfxstm32l152.git', '7f4389efee9c6a655b55e5df3fceef5586b35f9b', From 90080d4326ba2d3ce7f3cc43fc9ad699404d77ff Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 4 Sep 2025 17:24:00 +0700 Subject: [PATCH 354/382] update pio-usb --- tools/get_deps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/get_deps.py b/tools/get_deps.py index ce838e427..6e879d70d 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -59,7 +59,7 @@ deps_optional = { 'a1bdae309a14ec95a4f64a96d3315a4f89c397c6', 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'], 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/sekigon-gonnoc/Pico-PIO-USB.git', - '3c1eec341a5232640e4c00628b889b641af34b28', + '675543bcc9baa8170f868ab7ba316d418dbcf41f', 'rp2040'], 'hw/mcu/renesas/fsp': ['https://github.com/renesas/fsp.git', 'edcc97d684b6f716728a60d7a6fea049d9870bd6', From 89f8fbc9c2cc04e6e1dfcb28bb10a0ad76a966d5 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 4 Sep 2025 17:59:10 +0700 Subject: [PATCH 355/382] Create comprehensive GitHub Copilot instructions and fix pre-commit configuration for TinyUSB (#3234) * Initial plan * Create comprehensive GitHub Copilot instructions for TinyUSB Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Remove accidentally committed dependencies, use tools/get_deps.py instead Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Fix .gitignore: ignore vendor/ directory not ceedling script Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Revert .gitignore changes and add README_processed.rst Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Remove README_processed.rst and revert ceedling file permissions Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Changes before error encountered Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Remove redundant manual validation step, keep only pre-commit and build validation Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * fix pre-commit --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: hathach <249515+hathach@users.noreply.github.com> --- .github/copilot-instructions.md | 133 ++++++++++++++++++++++++++++++++ .gitignore | 1 + 2 files changed, 134 insertions(+) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..572b8d6f5 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,133 @@ +# TinyUSB +TinyUSB is an open-source cross-platform USB Host/Device stack for embedded systems, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events deferred to non-ISR task functions. + +Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here. + +## Working Effectively + +### Bootstrap and Build Setup +- Install ARM GCC toolchain: `sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi` +- Fetch core dependencies: `python3 tools/get_deps.py` -- takes <1 second. NEVER CANCEL. +- For specific board families: `python3 tools/get_deps.py FAMILY_NAME` (e.g., rp2040, stm32f4) +- Dependencies are cached in `lib/` and `hw/mcu/` directories + +### Build Examples +Choose ONE of these approaches: + +**Option 1: Individual Example with CMake (RECOMMENDED)** +```bash +cd examples/device/cdc_msc +mkdir -p build && cd build +cmake -DBOARD=stm32f407disco -DCMAKE_BUILD_TYPE=MinSizeRel .. +cmake --build . -j4 +``` +-- takes 1-2 seconds. NEVER CANCEL. Set timeout to 5+ minutes. + +**Option 2: Individual Example with Make** +```bash +cd examples/device/cdc_msc +make BOARD=stm32f407disco all +``` +-- takes 2-3 seconds. NEVER CANCEL. Set timeout to 5+ minutes. + +**Option 3: All Examples for a Board** +```bash +python3 tools/build.py -b BOARD_NAME +``` +-- takes 15-20 seconds, may have some objcopy failures that are non-critical. NEVER CANCEL. Set timeout to 30+ minutes. + +### Unit Testing +- Install Ceedling: `sudo gem install ceedling` +- Run all unit tests: `cd test/unit-test && ceedling` -- takes 4 seconds. NEVER CANCEL. Set timeout to 10+ minutes. +- Tests use Unity framework with CMock for mocking + +### Documentation +- Install requirements: `pip install -r docs/requirements.txt` +- Build docs: `cd docs && sphinx-build -b html . _build` -- takes 2-3 seconds. NEVER CANCEL. Set timeout to 10+ minutes. + +### Code Quality and Validation +- Format code: `clang-format -i path/to/file.c` (uses `.clang-format` config) +- Check spelling: `pip install codespell && codespell` (uses `.codespellrc` config) +- Pre-commit hooks validate unit tests and code quality automatically + +## Validation + +### ALWAYS Run These After Making Changes +1. **Pre-commit validation** (RECOMMENDED): `pre-commit run --all-files` + - Install pre-commit: `pip install pre-commit && pre-commit install` + - Runs all quality checks, unit tests, spell checking, and formatting + - Takes 10-15 seconds. NEVER CANCEL. Set timeout to 15+ minutes. +2. **Build validation**: Build at least one example that exercises your changes + ```bash + cd examples/device/cdc_msc + make BOARD=stm32f407disco all + ``` + +### Manual Testing Scenarios +- **Device examples**: Cannot be fully tested without real hardware, but must build successfully +- **Unit tests**: Exercise core stack functionality - ALL tests must pass +- **Build system**: Must be able to build examples for multiple board families + +### Board Selection for Testing +- **STM32F4**: `stm32f407disco` - no external SDK required, good for testing +- **RP2040**: `pico_sdk` - requires Pico SDK, commonly used +- **Other families**: Check `hw/bsp/FAMILY/boards/` for available boards + +## Common Tasks and Time Expectations + +### Repository Structure Quick Reference +``` +├── src/ # Core TinyUSB stack +│ ├── class/ # USB device classes (CDC, HID, MSC, Audio, etc.) +│ ├── portable/ # MCU-specific drivers (organized by vendor) +│ ├── device/ # USB device stack core +│ ├── host/ # USB host stack core +│ └── common/ # Shared utilities (FIFO, etc.) +├── examples/ # Example applications +│ ├── device/ # Device examples (cdc_msc, hid_generic, etc.) +│ ├── host/ # Host examples +│ └── dual/ # Dual-role examples +├── hw/bsp/ # Board Support Packages +│ └── FAMILY/boards/ # Board-specific configurations +├── test/unit-test/ # Unit tests using Ceedling +├── tools/ # Build and utility scripts +└── docs/ # Sphinx documentation +``` + +### Build Time Reference +- **Dependency fetch**: <1 second +- **Single example build**: 1-3 seconds +- **Unit tests**: ~4 seconds +- **Documentation build**: ~2.5 seconds +- **Full board examples**: 15-20 seconds +- **Toolchain installation**: 2-5 minutes (one-time) + +### Key Files to Know +- `tools/get_deps.py`: Manages dependencies for MCU families +- `tools/build.py`: Builds multiple examples, supports make/cmake +- `src/tusb.h`: Main TinyUSB header file +- `src/tusb_config.h`: Configuration template +- `examples/device/cdc_msc/`: Most commonly used example for testing +- `test/unit-test/project.yml`: Ceedling test configuration + +### Debugging Build Issues +- **Missing compiler**: Install `gcc-arm-none-eabi` package +- **Missing dependencies**: Run `python3 tools/get_deps.py FAMILY` +- **Board not found**: Check `hw/bsp/FAMILY/boards/` for valid board names +- **objcopy errors**: Often non-critical in full builds, try individual example builds + +### Working with USB Device Classes +- **CDC (Serial)**: `src/class/cdc/` - Virtual serial port +- **HID**: `src/class/hid/` - Human Interface Device (keyboard, mouse, etc.) +- **MSC**: `src/class/msc/` - Mass Storage Class (USB drive) +- **Audio**: `src/class/audio/` - USB Audio Class +- Each class has device (`*_device.c`) and host (`*_host.c`) implementations + +### MCU Family Support +- **STM32**: Largest support (F0, F1, F2, F3, F4, F7, G0, G4, H7, L4, U5, etc.) +- **Raspberry Pi**: RP2040, RP2350 with PIO-USB host support +- **NXP**: iMXRT, Kinetis, LPC families +- **Microchip**: SAM D/E/G/L families +- Check `hw/bsp/` for complete list and `docs/reference/boards.rst` for details + +Remember: TinyUSB is designed for embedded systems - builds are fast, tests are focused, and the codebase is optimized for resource-constrained environments. diff --git a/.gitignore b/.gitignore index 5638a09db..a4045f120 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,4 @@ RelWithDebInfo Release BrowseInfo .cmake_build +README_processed.rst From 3b983cb3e97e55c38959b7cf92c8fd65ca118095 Mon Sep 17 00:00:00 2001 From: zhiqiang Date: Fri, 5 Sep 2025 09:57:38 +0800 Subject: [PATCH 356/382] the family name error of at32 has been corrected --- docs/reference/boards.rst | 2 +- hw/bsp/at32f402_405/family.c | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index d984b3529..a8d73de5f 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -41,7 +41,7 @@ at_start_f413 AT-START-F413 at32f413 https://www.arterychip.com/en/pro at_start_f415 AT-START-F415 at32f415 https://www.arterychip.com/en/product/AT32F415.jsp at_start_f423 AT-START-F423 at32f423 https://www.arterychip.com/en/product/AT32F423.jsp at_start_f425 AT-START-F425 at32f425 https://www.arterychip.com/en/product/AT32F425.jsp -at_start_f435 AT-START-F435 at32f435_435 https://www.arterychip.com/en/product/AT32F435.jsp +at_start_f435 AT-START-F435 at32f435_437 https://www.arterychip.com/en/product/AT32F435.jsp at_start_f437 AT-START-F437 at32f435_437 https://www.arterychip.com/en/product/AT32F437.jsp ============== ============== ============= ================================================== ====== diff --git a/hw/bsp/at32f402_405/family.c b/hw/bsp/at32f402_405/family.c index 6b69c0157..cb5987cd4 100644 --- a/hw/bsp/at32f402_405/family.c +++ b/hw/bsp/at32f402_405/family.c @@ -163,7 +163,11 @@ void usb_clock48m_select(usb_clk48_s clk_s) void usb_gpio_config(void) { - /*if needed*/ + /* When the USB clock is enabled, the hardware will automatically + configure the pins; but other special pins that need to be used, + such as the pins used to detect VBUS or the pins that output the + SOF signal, still need to be configured separately, and these pins + are usually not required */ } /** From a379efcbf5f7ca53ec182649af7c72f705595bb4 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 5 Sep 2025 10:15:19 +0700 Subject: [PATCH 357/382] fix pre-commit --- hw/bsp/at32f435_437/family.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/at32f435_437/family.cmake b/hw/bsp/at32f435_437/family.cmake index 7bb38eb2f..085e5462b 100644 --- a/hw/bsp/at32f435_437/family.cmake +++ b/hw/bsp/at32f435_437/family.cmake @@ -56,7 +56,7 @@ function(add_board_target BOARD_TARGET) BOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED BOARD_TUH_MAX_SPEED=OPT_MODE_FULL_SPEED ) - + update_board(${BOARD_TARGET}) if (CMAKE_C_COMPILER_ID STREQUAL "GNU") From 0263cfc01ab63d6799e80cbbf691af1979cf3ab7 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Sat, 6 Sep 2025 06:58:35 -0700 Subject: [PATCH 358/382] fix #3239: discard poorly formed packets --- src/class/midi/midi_host.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 50bda1e36..e6ace316c 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -575,6 +575,11 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff } } } + else { + // bad packet discard + nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); + continue; + } } else if (status < MIDI_STATUS_SYSEX_START) { // then it is a channel message either three bytes or two uint8_t fake_cin = (status & 0xf0) >> 4; @@ -617,6 +622,11 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff bytes_to_add_to_stream = 1; } } + else { + // bad packet discard + nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); + continue; + } for (uint8_t i = 1; i <= bytes_to_add_to_stream; i++) { *p_buffer++ = p_midi->stream_read.buffer[i]; From d70d4043dcccb1628424c39c231ed1f95fb52f8e Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Sep 2025 16:59:26 +0700 Subject: [PATCH 359/382] use tusb_time_delay_ms_api for delay, also move tusb_time api to common.h --- src/common/tusb_common.h | 8 +++++++- src/portable/synopsys/dwc2/dwc2_stm32.h | 3 +-- src/tusb.h | 10 ---------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 0351a3d8f..b5bdb76e3 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -78,10 +78,16 @@ #include "tusb_debug.h" //--------------------------------------------------------------------+ -// Optional API implemented by application if needed +// API implemented by application if needed // TODO move to a more obvious place/file //--------------------------------------------------------------------+ +// Get current milliseconds, required by some port/configuration without RTOS +extern uint32_t tusb_time_millis_api(void); + +// Delay in milliseconds, use tusb_time_millis_api() by default. required by some port/configuration with no RTOS +extern void tusb_time_delay_ms_api(uint32_t ms); + // flush data cache TU_ATTR_WEAK extern void tusb_app_dcache_flush(uintptr_t addr, uint32_t data_size); diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 0bbad55f5..14d95184e 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -224,8 +224,7 @@ static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN; // Wait ~2ms until the PLL is ready (there's no RDY bit to query) - uint32_t count = (SystemCoreClock / 1000) * 2; - while (count--) __NOP(); + tusb_time_delay_ms_api(2); #else #endif diff --git a/src/tusb.h b/src/tusb.h index dfba21ddf..88815def1 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -169,16 +169,6 @@ void tusb_int_handler(uint8_t rhport, bool in_isr); #endif -//--------------------------------------------------------------------+ -// API Implemented by user -//--------------------------------------------------------------------+ - -// Get current milliseconds, required by some port/configuration without RTOS -uint32_t tusb_time_millis_api(void); - -// Delay in milliseconds, use tusb_time_millis_api() by default. required by some port/configuration with no RTOS -void tusb_time_delay_ms_api(uint32_t ms); - #ifdef __cplusplus } #endif From 19f67ffc22bcf9a59125b0f992bf6e8ee9819eec Mon Sep 17 00:00:00 2001 From: Dalton Caron Date: Tue, 9 Sep 2025 14:09:26 -0700 Subject: [PATCH 360/382] Initial STM32WBARI eval support Clean up includes definitions Remove wait that is not required Remove redundant settings Clean up clock configuration to look like other modules Remove MSP_Init that is not required Clean up driver code dhcp: Fix DHCP_OFFER/DHCP_ACK destinaton. In RFC 2131, the destination of DHCP OFFER/ACK is defined in Section 4.1. Fix the destination error by following the rule of RFC 2131. TODO: We implement all rule but the last one. ARP table is required to associate client's macaddr. Currently, fallback to broadcast. Signed-off-by: Elwin Huang Fix compile error. Fix goto indentation Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Fix osal_spin_unlock for mynewt Mynewt version for osal_spin_unlock() called OS_ENTER_CRITICAL instead of OS_EXIT_CRITICAL. Signed-off-by: Jerzy Kasenberg Add ESP32-C5 and ESP32-C61 definitions fix(dcd/dwc2): Fix reset procedure for versions >=4.20a Fix STM32L4 GPIOD clock enable for variants without GPIOD Add weact blackpill support Add to boards.rst file Fix file Small cleanups. Insert small delay for LowSpeed device Improve retry operation at NAK response. Remove dynamic memory allocation use tusb_time_millis_api() instead of board_millis() make loopdelay() always inline update at32f405 dwc2 info and phy width selection add at32f415 dwc2 info add some consumer page configs remove duplicated enum Initial plan Fix obsolete cnt assignment in _tu_fifo_peek() overflow check Co-authored-by: hathach <249515+hathach@users.noreply.github.com> Initial plan Update STM32 CMSIS dependencies to fix HSITRIM register bug Co-authored-by: hathach <249515+hathach@users.noreply.github.com> Remove accidentally committed dependency directories Co-authored-by: hathach <249515+hathach@users.noreply.github.com> Update all STM32 HAL driver dependencies to latest versions Co-authored-by: hathach <249515+hathach@users.noreply.github.com> fix linker h745 issue with clang fix linker h745 issue with clang Update all STM32 CMSIS device dependencies to latest versions Co-authored-by: hathach <249515+hathach@users.noreply.github.com> update pio-usb Create comprehensive GitHub Copilot instructions and fix pre-commit configuration for TinyUSB (#3234) * Initial plan * Create comprehensive GitHub Copilot instructions for TinyUSB Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Remove accidentally committed dependencies, use tools/get_deps.py instead Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Fix .gitignore: ignore vendor/ directory not ceedling script Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Revert .gitignore changes and add README_processed.rst Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Remove README_processed.rst and revert ceedling file permissions Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Changes before error encountered Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * Remove redundant manual validation step, keep only pre-commit and build validation Co-authored-by: hathach <249515+hathach@users.noreply.github.com> * fix pre-commit --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: hathach <249515+hathach@users.noreply.github.com> modified the bsp files of at32 to make them work better the family name error of at32 has been corrected fix pre-commit STM32N6570-DK board is added. Build with DEBUG=1 (make BOARD=stm32n6570dk DEBUG=1 all), otherwise it does not work for now. Tested with examples/device/cdc_dual_ports --- docs/reference/boards.rst | 1 + docs/reference/dependencies.rst | 1 + .../stm32wba/FreeRTOSConfig/FreeRTOSConfig.h | 153 ++++++++ .../stm32wba/boards/stm32wba_eval/board.cmake | 10 + hw/bsp/stm32wba/boards/stm32wba_eval/board.h | 136 +++++++ hw/bsp/stm32wba/boards/stm32wba_eval/board.mk | 6 + .../include/stm32wbaxx_hal_conf.h | 368 ++++++++++++++++++ hw/bsp/stm32wba/family.c | 233 +++++++++++ hw/bsp/stm32wba/family.mk | 59 +++ hw/bsp/stm32wba/stm32wbaxx_hal_conf.h | 367 +++++++++++++++++ src/common/tusb_mcu.h | 6 + src/portable/st/stm32_fsdev/fsdev_stm32.h | 8 + src/portable/synopsys/dwc2/dwc2_common.c | 5 + src/portable/synopsys/dwc2/dwc2_stm32.h | 23 +- src/tusb_option.h | 1 + tools/get_deps.py | 6 + 16 files changed, 1381 insertions(+), 2 deletions(-) create mode 100644 hw/bsp/stm32wba/FreeRTOSConfig/FreeRTOSConfig.h create mode 100644 hw/bsp/stm32wba/boards/stm32wba_eval/board.cmake create mode 100644 hw/bsp/stm32wba/boards/stm32wba_eval/board.h create mode 100644 hw/bsp/stm32wba/boards/stm32wba_eval/board.mk create mode 100644 hw/bsp/stm32wba/boards/stm32wba_eval/include/stm32wbaxx_hal_conf.h create mode 100644 hw/bsp/stm32wba/family.c create mode 100644 hw/bsp/stm32wba/family.mk create mode 100644 hw/bsp/stm32wba/stm32wbaxx_hal_conf.h diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index 71dca8e94..a930f485b 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -303,6 +303,7 @@ stm32u575eval STM32 U575 Eval stm32u5 https://www.s stm32u575nucleo STM32 U575 Nucleo stm32u5 https://www.st.com/en/evaluation-tools/nucleo-u575zi-q.html stm32u5a5nucleo STM32 U5a5 Nucleo stm32u5 https://www.st.com/en/evaluation-tools/nucleo-u5a5zj-q.html stm32wb55nucleo STM32 P-NUCLEO-WB55 stm32wb https://www.st.com/en/evaluation-tools/p-nucleo-wb55.html +stm32wba65nucleo STM32 NUCLEO-WBA65RI stm32wba https://www.st.com/en/evaluation-tools/nucleo-wba65ri.html =================== ================================= ========= ================================================================= ====== Sunxi diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index d75139aae..8a65eee86 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -71,6 +71,7 @@ hw/mcu/st/stm32l5xx_hal_driver https://github.com/STMicroelectronics/ hw/mcu/st/stm32n6xx_hal_driver https://github.com/STMicroelectronics/stm32n6xx-hal-driver.git 49f9989d10cf6817d4b07ac01848956b46bd0fd6 stm32n6 hw/mcu/st/stm32u5xx_hal_driver https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git 4d93097a67928e9377e655ddd14622adc31b9770 stm32u5 hw/mcu/st/stm32wbxx_hal_driver https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git 2c5f06638be516c1b772f768456ba637f077bac8 stm32wb +hw/mcu/st/stm32wbaxx_hal_driver https://github.com/STMicroelectronics/stm32wbaxx-hal-driver.git 9442fbb71f855ff2e64fbf662b7726beba511a24 stm32wba hw/mcu/ti https://github.com/hathach/ti_driver.git 143ed6cc20a7615d042b03b21e070197d473e6e5 msp430 msp432e4 tm4c hw/mcu/wch/ch32f20x https://github.com/openwch/ch32f20x.git 77c4095087e5ed2c548ec9058e655d0b8757663b ch32f20x hw/mcu/wch/ch32v103 https://github.com/openwch/ch32v103.git 7578cae0b21f86dd053a1f781b2fc6ab99d0ec17 ch32v10x diff --git a/hw/bsp/stm32wba/FreeRTOSConfig/FreeRTOSConfig.h b/hw/bsp/stm32wba/FreeRTOSConfig/FreeRTOSConfig.h new file mode 100644 index 000000000..471d56aec --- /dev/null +++ b/hw/bsp/stm32wba/FreeRTOSConfig/FreeRTOSConfig.h @@ -0,0 +1,153 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html. + *----------------------------------------------------------*/ + +// skip if included from IAR assembler +#ifndef __IASMARM__ + #include "stm32wbaxx.h" +#endif + +/* Cortex M23/M33 port configuration. */ +#define configENABLE_MPU 0 +#if defined(__ARM_FP) && __ARM_FP >= 4 + #define configENABLE_FPU 1 +#else + #define configENABLE_FPU 0 +#endif +#define configENABLE_TRUSTZONE 0 +#define configMINIMAL_SECURE_STACK_SIZE (1024) + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#define configCPU_CLOCK_HZ SystemCoreClock +#define configTICK_RATE_HZ ( 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( 128 ) +#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) +#define configMAX_TASK_NAME_LEN 16 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configQUEUE_REGISTRY_SIZE 4 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TIME_SLICING 0 +#define configUSE_NEWLIB_REENTRANT 0 +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 + +#define configSUPPORT_STATIC_ALLOCATION 1 +#define configSUPPORT_DYNAMIC_ALLOCATION 0 + +/* Hook function related definitions. */ +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configCHECK_HANDLER_INSTALLATION 0 + +/* Run time and task stats gathering related definitions. */ +#define configGENERATE_RUN_TIME_STATS 0 +#define configRECORD_STACK_HIGH_ADDRESS 1 +#define configUSE_TRACE_FACILITY 1 // legacy trace +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES 2 + +/* Software timer related definitions. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) +#define configTIMER_QUEUE_LENGTH 32 +#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE + +/* Optional functions - most linkers will remove unused functions anyway. */ +#define INCLUDE_vTaskPrioritySet 0 +#define INCLUDE_uxTaskPriorityGet 0 +#define INCLUDE_vTaskDelete 0 +#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY +#define INCLUDE_xResumeFromISR 0 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_xTaskGetSchedulerState 0 +#define INCLUDE_xTaskGetCurrentTaskHandle 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 +#define INCLUDE_pcTaskGetTaskName 0 +#define INCLUDE_eTaskGetState 0 +#define INCLUDE_xEventGroupSetBitFromISR 0 +#define INCLUDE_xTimerPendFunctionCall 0 + +/* FreeRTOS hooks to NVIC vectors */ +#define xPortPendSVHandler PendSV_Handler +#define xPortSysTickHandler SysTick_Handler +#define vPortSVCHandler SVC_Handler + +//--------------------------------------------------------------------+ +// Interrupt nesting behavior configuration. +//--------------------------------------------------------------------+ + +// For Cortex-M specific: __NVIC_PRIO_BITS is defined in mcu header +#define configPRIO_BITS 4 + +/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ +#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< + +#include "stm32wbaxx_hal.h" +#include "bsp/board_api.h" +#include "board.h" + + //--------------------------------------------------------------------+ + // MACRO TYPEDEF CONSTANT ENUM + //--------------------------------------------------------------------+ +#ifndef CFG_BOARD_UART_BAUDRATE +#define CFG_BOARD_UART_BAUDRATE 115200 +#endif + +#ifndef USART_TIMEOUT_TICKS +#define USART_TIMEOUT_TICKS 1000 +#endif + +static UART_HandleTypeDef uart_handle; + +//--------------------------------------------------------------------+ +// Forward USB interrupt events to TinyUSB IRQ Handler +//--------------------------------------------------------------------+ +void USB_OTG_HS_IRQHandler( void ) +{ + tud_int_handler( 0 ); +} + +//--------------------------------------------------------------------+ +// Board porting API +//--------------------------------------------------------------------+ + +static void board_gpio_configuration( void ) +{ + GPIO_InitTypeDef gpio_init = { 0 }; + + USART_GPIO_CLK_EN(); + USART_CLK_EN(); + + // Configure USART TX pin + gpio_init.Pin = USART_TX_PIN; + gpio_init.Mode = GPIO_MODE_AF_PP; + gpio_init.Pull = GPIO_NOPULL; + gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; + gpio_init.Alternate = USART_GPIO_AF; + HAL_GPIO_Init( USART_TX_GPIO_PORT, &gpio_init ); + + // Configure USART RX pin + gpio_init.Pin = USART_RX_PIN; + gpio_init.Mode = GPIO_MODE_AF_PP; + gpio_init.Pull = GPIO_PULLUP; + gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; + gpio_init.Alternate = USART_GPIO_AF; + HAL_GPIO_Init( USART_RX_GPIO_PORT, &gpio_init ); + + // Configure the LED + LED_CLK_EN(); + gpio_init.Pin = LED_PIN; + gpio_init.Mode = GPIO_MODE_OUTPUT_PP; + gpio_init.Pull = GPIO_PULLUP; + gpio_init.Speed = GPIO_SPEED_FREQ_LOW; + gpio_init.Alternate = 0; + HAL_GPIO_Init( LED_PORT, &gpio_init ); + + // Default LED state is off + board_led_write( false ); + + // Configure the button + BUTTON_CLK_EN(); + gpio_init.Pin = BUTTON_PIN; + gpio_init.Mode = GPIO_MODE_INPUT; + gpio_init.Pull = GPIO_PULLUP; + gpio_init.Speed = GPIO_SPEED_FREQ_LOW; + gpio_init.Alternate = 0; + HAL_GPIO_Init( BUTTON_PORT, &gpio_init ); + + // Configure USB DM and DP pins. This is optional, and maintained only for user guidance. + gpio_init.Pin = (GPIO_PIN_7 | GPIO_PIN_6); + gpio_init.Mode = GPIO_MODE_INPUT; + gpio_init.Pull = GPIO_NOPULL; + gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init( GPIOD, &gpio_init ); +} + +static void board_uart_configuration( void ) +{ + uart_handle = ( UART_HandleTypeDef ) { + .Instance = USART_DEV, + .Init.BaudRate = CFG_BOARD_UART_BAUDRATE, + .Init.WordLength = UART_WORDLENGTH_8B, + .Init.StopBits = UART_STOPBITS_1, + .Init.Parity = UART_PARITY_NONE, + .Init.HwFlowCtl = UART_HWCONTROL_NONE, + .Init.Mode = UART_MODE_TX_RX, + .Init.OverSampling = UART_OVERSAMPLING_16 + }; + HAL_UART_Init( &uart_handle ); +} + +void board_init( void ) +{ + board_system_clock_config(); + board_gpio_configuration(); + board_uart_configuration(); + +#ifdef USB_OTG_HS + // STM32WBA65/64/62 only has 1 USB HS port + + #if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config( SystemCoreClock / 1000 ); + #elif CFG_TUSB_OS == OPT_OS_FREERTOS + // Explicitly disable systick to prevent its ISR runs before scheduler start + SysTick->CTRL &= ~1U; + + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority( OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); + #endif + + // USB clock enable + __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + __HAL_RCC_USB_OTG_HS_PHY_CLK_ENABLE(); + + // See the reference manual section 11.4.7 for the USB OTG powering sequence + + // Remove the VDDUSB power isolation + PWR->SVMCR |= PWR_SVMCR_USV; + + // Enable VDD11USB supply by clearing VDD11USBDIS to 0 + PWR->VOSR &= ~PWR_VOSR_VDD11USBDIS; + + // Enable USB OTG internal power by setting USBPWREN to 1 + PWR->VOSR |= PWR_VOSR_USBPWREN; + + // Wait for VDD11USB supply to be ready in VDD11USBRDY = 1 + while ((PWR->VOSR & PWR_VOSR_VDD11USBRDY) == 0) {} + + // Enable USB OTG booster by setting USBBOOSTEN to 1 + PWR->VOSR |= PWR_VOSR_USBBOOSTEN; + + // Wait for USB OTG booster to be ready in USBBOOSTRDY = 1 + while ((PWR->VOSR & PWR_VOSR_USBBOOSTRDY) == 0) {} + + // Enable USB power on Pwrctrl CR2 register + PWR->SVMCR |= PWR_SVMCR_USV; + + // Set the reference clock selection (must match the clock source) + SYSCFG->OTGHSPHYCR &= ~SYSCFG_OTGHSPHYCR_CLKSEL; + SYSCFG->OTGHSPHYCR |= SYSCFG_OTGHSPHYCR_CLKSEL_0 | SYSCFG_OTGHSPHYCR_CLKSEL_1 | + SYSCFG_OTGHSPHYCR_CLKSEL_3; // 32MHz clock + + // Configuring the SYSCFG registers OTG_HS PHY + SYSCFG->OTGHSPHYCR |= SYSCFG_OTGHSPHYCR_EN; + + // Disable VBUS sense (B device) + USB_OTG_HS->GCCFG &= ~USB_OTG_GCCFG_VBDEN; + + // B-peripheral session valid override enable + USB_OTG_HS->GCCFG |= USB_OTG_GCCFG_VBVALEXTOEN; + USB_OTG_HS->GCCFG |= USB_OTG_GCCFG_VBVALOVAL; +#endif // USB_OTG_FS +} + +void board_led_write( bool state ) +{ + HAL_GPIO_WritePin( LED_PORT, LED_PIN, state ? LED_STATE_ON : ( 1 - LED_STATE_ON ) ); +} + +uint32_t board_button_read( void ) +{ + return HAL_GPIO_ReadPin( BUTTON_PORT, BUTTON_PIN ) == BUTTON_STATE_ACTIVE; +} + +int board_uart_read( uint8_t *buf, int len ) +{ + ( void ) buf; + ( void ) len; + return 0; +} + +int board_uart_write( void const *buf, int len ) +{ + ( void ) HAL_UART_Transmit( &uart_handle, ( const uint8_t * ) buf, len, USART_TIMEOUT_TICKS ); + return len; +} + +#if CFG_TUSB_OS == OPT_OS_NONE +volatile uint32_t system_ticks = 0; +void SysTick_Handler( void ) +{ + HAL_IncTick(); + system_ticks++; +} + +uint32_t board_millis( void ) +{ + return system_ticks; +} +#endif + +void HardFault_Handler( void ) +{ + asm( "bkpt 1" ); +} + +// Required by __libc_init_array in startup code if we are compiling using -nostdlib/-nostartfiles. +void _init( void ); +void _init( void ) +{ } diff --git a/hw/bsp/stm32wba/family.mk b/hw/bsp/stm32wba/family.mk new file mode 100644 index 000000000..ca6459ab2 --- /dev/null +++ b/hw/bsp/stm32wba/family.mk @@ -0,0 +1,59 @@ +UF2_FAMILY_ID = 0x70d16657 +ST_FAMILY = wba + +ST_PREFIX = stm32${ST_FAMILY}xx +ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver + +include $(TOP)/$(BOARD_PATH)/board.mk +CPU_CORE ?= cortex-m33 + +CFLAGS += \ + -DCFG_TUSB_MCU=OPT_MCU_STM32WBA + +CFLAGS_GCC += \ + -flto \ + -nostdlib -nostartfiles \ + -Wno-error=cast-align -Wno-unused-parameter + +LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs -Wl,--gc-sections + +SRC_C += \ + src/portable/synopsys/dwc2/dcd_dwc2.c \ + src/portable/synopsys/dwc2/hcd_dwc2.c \ + src/portable/synopsys/dwc2/dwc2_common.c \ + $(ST_CMSIS)/Source/Templates/system_${ST_PREFIX}.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_cortex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_icache.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pwr.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pwr_ex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_rcc.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_rcc_ex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_uart.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_gpio.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pcd.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pcd_ex.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_ll_usb.c \ + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal.c + +INC += \ + $(TOP)/$(BOARD_PATH) \ + $(TOP)/$(BOARD_PATH)/include \ + $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \ + $(TOP)/$(ST_CMSIS)/Include \ + $(TOP)/$(ST_HAL_DRIVER)/Inc + +# STM32WBA HAL uses uppercase MCU_VARIANT (excluding the x's) for linking and lowercase MCU_VARIANT for startup. +UPPERCASE_MCU_VARIANT = $(shell echo $(MCU_VARIANT) | sed 's/\([^x]\)/\U\1/g') + +# Startup - Manually specify lowercase version for startup file +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_$(MCU_VARIANT).s +SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT).s + +# Linker +LD_FILE_GCC ?= ${ST_CMSIS}/Source/Templates/gcc/linker/${UPPERCASE_MCU_VARIANT}_FLASH_ns.ld +LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash_cm33.icf + +# flash target using on-board stlink +flash: flash-stlink \ No newline at end of file diff --git a/hw/bsp/stm32wba/stm32wbaxx_hal_conf.h b/hw/bsp/stm32wba/stm32wbaxx_hal_conf.h new file mode 100644 index 000000000..f4e49f341 --- /dev/null +++ b/hw/bsp/stm32wba/stm32wbaxx_hal_conf.h @@ -0,0 +1,367 @@ +/** + ****************************************************************************** + * @file stm32wbaxx_hal_conf_template.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32wbaxx_hal_conf.h. + ****************************************************************************** + * @attention + * + * Copyright (c) 2022 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32WBAxx_HAL_CONF_H +#define STM32WBAxx_HAL_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED +// #define HAL_ADC_MODULE_ENABLED +// #define HAL_COMP_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +// #define HAL_CRC_MODULE_ENABLED +// #define HAL_CRYP_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_GTZC_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_HSEM_MODULE_ENABLED +// #define HAL_I2C_MODULE_ENABLED +#define HAL_ICACHE_MODULE_ENABLED +// #define HAL_IRDA_MODULE_ENABLED +// #define HAL_IWDG_MODULE_ENABLED +// #define HAL_LPTIM_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +// #define HAL_PKA_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RAMCFG_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +// #define HAL_RNG_MODULE_ENABLED +// #define HAL_RTC_MODULE_ENABLED +// #define HAL_SAI_MODULE_ENABLED +// #define HAL_SMARTCARD_MODULE_ENABLED +// #define HAL_SMBUS_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +// #define HAL_TSC_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +// #define HAL_WWDG_MODULE_ENABLED +// #define HAL_XSPI_MODULE_ENABLED + +/* ########################## Oscillator Values adaptation ####################*/ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) +#define HSE_VALUE 32000000UL /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) +#define HSE_STARTUP_TIMEOUT 100UL /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) +#define HSI_VALUE 16000000UL /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) +#define LSI_VALUE 32000UL /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations in voltage + and temperature.*/ + +#if defined (RCC_LSI2_SUPPORT) +#if !defined (LSI2_VALUE) +#define LSI2_VALUE 32000UL /*!< LSI2 Typical Value in Hz*/ +#endif /* LSI2_VALUE */ +#endif + +/** + * @brief External Low Speed oscillator (LSE) value. + * This value is used by the UART, RTC HAL module to compute the system frequency + */ +#if !defined (LSE_VALUE) +#define LSE_VALUE 32768UL /*!< Value of the External oscillator in Hz*/ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) +#define LSE_STARTUP_TIMEOUT 5000UL /*!< Time out for LSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for SAI1 peripheral + * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source + * frequency. + */ +#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) +#define EXTERNAL_SAI1_CLOCK_VALUE 48000UL /*!< Value of the SAI1 External clock source in Hz*/ +#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300UL /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((1UL<<__NVIC_PRIO_BITS) - 1UL) /*!< tick interrupt priority (lowest by default) */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U /*!< Enable prefetch */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Register callback feature configuration ############### */ +/** + * @brief Set below the peripheral configuration to "1U" to add the support + * of HAL callback registration/unregistration feature for the HAL + * driver(s). This allows user application to provide specific callback + * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting + * the default weak callback functions (see each stm32wbaxx_hal_ppp.h file + * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef + * for each PPP peripheral). + */ +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U /* IWDG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_PKA_REGISTER_CALLBACKS 0U /* PKA register callback disabled */ +#define USE_HAL_RAMCFG_REGISTER_CALLBACKS 0U /* RAMCFG register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_TSC_REGISTER_CALLBACKS 0U /* TSC register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ +#define USE_HAL_XSPI_REGISTER_CALLBACKS 0U /* XSPI register callback disabled */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver + * Activated: CRC code is present inside driver + * Deactivated: CRC code cleaned from driver + */ +#define USE_SPI_CRC 1U + +/* ################## CRYP peripheral configuration ########################## */ + +#define USE_HAL_CRYP_SUSPEND_RESUME 0U + +/* ################## HASH peripheral configuration ########################## */ + +#define USE_HAL_HASH_SUSPEND_RESUME 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ +#ifdef HAL_DMA_MODULE_ENABLED +#include "stm32wbaxx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_RCC_MODULE_ENABLED +#include "stm32wbaxx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED +#include "stm32wbaxx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_COMP_MODULE_ENABLED +#include "stm32wbaxx_hal_comp.h" +#endif /* HAL_COMP_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED +#include "stm32wbaxx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED +#include "stm32wbaxx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED +#include "stm32wbaxx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED +#include "stm32wbaxx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED +#include "stm32wbaxx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED +#include "stm32wbaxx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_GTZC_MODULE_ENABLED +#include "stm32wbaxx_hal_gtzc.h" +#endif /* HAL_GTZC_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED +#include "stm32wbaxx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED +#include "stm32wbaxx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_HSEM_MODULE_ENABLED +#include "stm32wbaxx_hal_hsem.h" +#endif /* HAL_HSEM_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED +#include "stm32wbaxx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_ICACHE_MODULE_ENABLED +#include "stm32wbaxx_hal_icache.h" +#endif /* HAL_ICACHE_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED +#include "stm32wbaxx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED +#include "stm32wbaxx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED +#include "stm32wbaxx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED +#include "stm32wbaxx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_PKA_MODULE_ENABLED +#include "stm32wbaxx_hal_pka.h" +#endif /* HAL_PKA_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED +#include "stm32wbaxx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RAMCFG_MODULE_ENABLED +#include "stm32wbaxx_hal_ramcfg.h" +#endif /* HAL_RAMCFG_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED +#include "stm32wbaxx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED +#include "stm32wbaxx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED +#include "stm32wbaxx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED +#include "stm32wbaxx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED +#include "stm32wbaxx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm32wbaxx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED +#include "stm32wbaxx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_TSC_MODULE_ENABLED +#include "stm32wbaxx_hal_tsc.h" +#endif /* HAL_TSC_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED +#include "stm32wbaxx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED +#include "stm32wbaxx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED +#include "stm32wbaxx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_XSPI_MODULE_ENABLED +#include "stm32wbaxx_hal_xspi.h" +#endif /* HAL_XSPI_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ +#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ +void assert_failed(uint8_t *file, uint32_t line); +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32WBAxx_HAL_CONF_H */ diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 3ffc2d1a4..7722ca1e6 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -295,6 +295,12 @@ #define TUP_USBIP_FSDEV_STM32 #define TUP_DCD_ENDPOINT_MAX 8 +#elif TU_CHECK_MCU(OPT_MCU_STM32WBA) + #define TUP_USBIP_DWC2 + #define TUP_USBIP_DWC2_STM32 + #define TUP_DCD_ENDPOINT_MAX 9 + #define TUP_RHPORT_HIGHSPEED 1 + #elif TU_CHECK_MCU(OPT_MCU_STM32U5) #if defined (STM32U535xx) || defined (STM32U545xx) #define TUP_USBIP_FSDEV diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index ccf31e035..01baf50ae 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -148,6 +148,12 @@ /* ST provided header has incorrect value of USB_PMAADDR */ #define FSDEV_PMA_BASE USB1_PMAADDR +#elif defined(STM32WBA62xx) || defined(STM32WBA64xx) || defined(STM32WBA65xx) + // Available only on STM32WBA62/64/65xx devices + #include "stm32wbaxx.h" + #define FSDEV_PMA_SIZE (2048u) + #define USB USB_DRD_FS + #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 #include "stm32l4xx.h" #define FSDEV_PMA_SIZE (1024u) @@ -289,6 +295,8 @@ static const IRQn_Type fsdev_irq[] = { USB_LP_IRQn, #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 USB_IRQn, + #elif CFG_TUSB_MCU == OPT_MCU_STM32WBA + USB_OTG_HS_IRQn, #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 USB_DRD_FS_IRQn, #else diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index d7d157149..f81cfceda 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -49,6 +49,11 @@ static void reset_core(dwc2_regs_t* dwc2) { uint32_t gsnpsid = dwc2->gsnpsid; // reset core + + // On the STM32WBA peripheral, the device seems to get stuck in reset unless + // this shadow register is utilized. + uint32_t gsnpsid = dwc2->gsnpsid; + dwc2->grstctl |= GRSTCTL_CSRST; if ((gsnpsid & DWC2_CORE_REV_MASK) < (DWC2_CORE_REV_4_20a & DWC2_CORE_REV_MASK)) { diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index 672891561..ca5ce5a7c 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -113,6 +113,22 @@ extern "C" { #define EP_MAX_HS 9 #define EP_FIFO_SIZE_HS 4096 #endif + +#elif CFG_TUSB_MCU == OPT_MCU_STM32WBA + #if defined(STM32WBA62xx) + #include "stm32wba62xx.h" + #elif defined(STM32WBA64xx) + #include "stm32wba64xx.h" + #elif defined(STM32WBA65xx) + #include "stm32wba65xx.h" + #else + #error "The selected STM32WBA series chip does not support OTG USB HS" + #endif + + #define USB_OTG_HS_PERIPH_BASE USB_OTG_HS_BASE_NS + #define OTG_HS_IRQn USB_OTG_HS_IRQn + #define EP_MAX_HS 9 + #define EP_FIFO_SIZE_HS 4096 #else #error "Unsupported MCUs" #endif @@ -166,6 +182,7 @@ TU_ATTR_ALWAYS_INLINE static inline void dwc2_remote_wakeup_delay(void) { // MCU specific PHY init, called BEFORE core reset // - dwc2 3.30a (H5) use USB_HS_PHYC // - dwc2 4.11a (U5) use femtoPHY +// - dwc2 x.xxx (WBA) use USB_OTG_HS static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { if (hs_phy_type == GHWCFG2_HSPHY_NOT_SUPPORTED) { // Enable on-chip FS PHY @@ -194,11 +211,10 @@ static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { #endif } else { -#if CFG_TUSB_MCU != OPT_MCU_STM32U5 +#if CFG_TUSB_MCU != OPT_MCU_STM32U5 && CFG_TUSB_MCU != OPT_MCU_STM32WBA // Disable FS PHY, TODO on U5A5 (dwc2 4.11a) 16th bit is 'Host CDP behavior enable' dwc2->stm32_gccfg &= ~STM32_GCCFG_PWRDWN; #endif - // Enable on-chip HS PHY if (hs_phy_type == GHWCFG2_HSPHY_UTMI || hs_phy_type == GHWCFG2_HSPHY_UTMI_ULPI) { #ifdef USB_HS_PHYC @@ -233,11 +249,14 @@ static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { // Enable PLL internal PHY USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN; +<<<<<<< HEAD // Wait ~2ms until the PLL is ready (there's no RDY bit to query) tusb_time_delay_ms_api(2); #else +======= +>>>>>>> 246a92c65 (It worksgit status!) #endif } } diff --git a/src/tusb_option.h b/src/tusb_option.h index 1533bb209..b2dd5fcb2 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -95,6 +95,7 @@ #define OPT_MCU_STM32H7RS 317 ///< ST F7RS #define OPT_MCU_STM32C0 318 ///< ST C0 #define OPT_MCU_STM32N6 319 ///< ST N6 +#define OPT_MCU_STM32WBA 320 ///< ST WBA // Sony #define OPT_MCU_CXD56 400 ///< SONY CXD56 diff --git a/tools/get_deps.py b/tools/get_deps.py index 36b4d2d59..37d541785 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -130,6 +130,9 @@ deps_optional = { 'hw/mcu/st/cmsis_device_wb': ['https://github.com/STMicroelectronics/cmsis_device_wb.git', 'cda2cb9fc4a5232ab18efece0bb06b0b60910083', 'stm32wb'], + 'hw/mcu/st/cmsis_device_wba': ['https://github.com/STMicroelectronics/cmsis-device-wba', + '647d8522e5fd15049e9a1cc30ed19d85e5911eaf', + 'stm32wba'], 'hw/mcu/st/stm32-mfxstm32l152': ['https://github.com/STMicroelectronics/stm32-mfxstm32l152.git', '7f4389efee9c6a655b55e5df3fceef5586b35f9b', 'stm32h7'], @@ -193,6 +196,9 @@ deps_optional = { 'hw/mcu/st/stm32wbxx_hal_driver': ['https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git', 'd60dd46996876506f1d2e9abd6b1cc110c8004cd', 'stm32wb'], + 'hw/mcu/st/stm32wbaxx_hal_driver': ['https://github.com/STMicroelectronics/stm32wbaxx_hal_driver.git', + '9442fbb71f855ff2e64fbf662b7726beba511a24', + 'stm32wba'], 'hw/mcu/ti': ['https://github.com/hathach/ti_driver.git', '143ed6cc20a7615d042b03b21e070197d473e6e5', 'msp430 msp432e4 tm4c'], From 48f6b95bd8b0c3d33832f289b02b53da410d5ef9 Mon Sep 17 00:00:00 2001 From: Dalton Caron Date: Tue, 9 Sep 2025 15:41:12 -0700 Subject: [PATCH 361/382] Incorporate upstream changes to dwc2_common.c --- src/portable/synopsys/dwc2/dwc2_common.c | 29 ++++++++++-------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index f81cfceda..9b8333ad2 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -49,11 +49,6 @@ static void reset_core(dwc2_regs_t* dwc2) { uint32_t gsnpsid = dwc2->gsnpsid; // reset core - - // On the STM32WBA peripheral, the device seems to get stuck in reset unless - // this shadow register is utilized. - uint32_t gsnpsid = dwc2->gsnpsid; - dwc2->grstctl |= GRSTCTL_CSRST; if ((gsnpsid & DWC2_CORE_REV_MASK) < (DWC2_CORE_REV_4_20a & DWC2_CORE_REV_MASK)) { @@ -100,14 +95,6 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; const dwc2_ghwcfg4_t ghwcfg4 = {.value = dwc2->ghwcfg4}; - uint8_t phy_width; - if (CFG_TUSB_MCU != OPT_MCU_AT32F402_405 && // at32f402_405 does not support 16-bit - ghwcfg4.phy_data_width) { - phy_width = 16; // 16-bit PHY interface if supported - } else { - phy_width = 8; // 8-bit PHY interface - } - // De-select FS PHY gusbcfg &= ~GUSBCFG_PHYSEL; @@ -135,10 +122,12 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { gusbcfg &= ~GUSBCFG_ULPI_UTMI_SEL; // Set 16-bit interface if supported - if (phy_width == 16) { - gusbcfg |= GUSBCFG_PHYIF16; + if (ghwcfg4.phy_data_width) { + #if CFG_TUSB_MCU != OPT_MCU_AT32F402_405 // at32f402_405 does not actually support 16-bit + gusbcfg |= GUSBCFG_PHYIF16; // 16 bit + #endif } else { - gusbcfg &= ~GUSBCFG_PHYIF16; + gusbcfg &= ~GUSBCFG_PHYIF16; // 8 bit } } @@ -155,7 +144,13 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { // - 9 if using 8-bit PHY interface // - 5 if using 16-bit PHY interface gusbcfg &= ~GUSBCFG_TRDT_Msk; - gusbcfg |= (phy_width == 16 ? 5u : 9u) << GUSBCFG_TRDT_Pos; + +#if CFG_TUSB_MCU == OPT_MCU_AT32F402_405 // at32f402_405 does not actually support 16-bit + gusbcfg |= 9u << GUSBCFG_TRDT_Pos; +#else + gusbcfg |= (dwc2->ghwcfg4_bm.phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos; +#endif + dwc2->gusbcfg = gusbcfg; // MCU specific PHY update post reset From 2e9ae5af203c211e9efe3c00a51179c3c883c2bd Mon Sep 17 00:00:00 2001 From: Dalton Caron Date: Wed, 10 Sep 2025 10:48:48 -0700 Subject: [PATCH 362/382] STM32WBARI eval CMake build support --- .../stm32wba/boards/stm32wba_eval/board.cmake | 6 +- .../include/stm32wbaxx_hal_conf.h | 368 ------------------ hw/bsp/stm32wba/family.cmake | 147 +++++++ hw/bsp/stm32wba/family.mk | 5 +- 4 files changed, 151 insertions(+), 375 deletions(-) delete mode 100644 hw/bsp/stm32wba/boards/stm32wba_eval/include/stm32wbaxx_hal_conf.h create mode 100644 hw/bsp/stm32wba/family.cmake diff --git a/hw/bsp/stm32wba/boards/stm32wba_eval/board.cmake b/hw/bsp/stm32wba/boards/stm32wba_eval/board.cmake index c0d1cbbcc..57bd920d3 100644 --- a/hw/bsp/stm32wba/boards/stm32wba_eval/board.cmake +++ b/hw/bsp/stm32wba/boards/stm32wba_eval/board.cmake @@ -1,10 +1,8 @@ set(MCU_VARIANT stm32wba65xx) -set(JLINK_DEVICE STM32WB65RI) - -set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/stm32wb65RIVX_FLASH.ld) +set(JLINK_DEVICE STM32WBA65RI) function(update_board TARGET) target_compile_definitions(${TARGET} PUBLIC - STM32WB65xx + STM32WBA65xx ) endfunction() diff --git a/hw/bsp/stm32wba/boards/stm32wba_eval/include/stm32wbaxx_hal_conf.h b/hw/bsp/stm32wba/boards/stm32wba_eval/include/stm32wbaxx_hal_conf.h deleted file mode 100644 index 419865492..000000000 --- a/hw/bsp/stm32wba/boards/stm32wba_eval/include/stm32wbaxx_hal_conf.h +++ /dev/null @@ -1,368 +0,0 @@ -/** - ****************************************************************************** - * @file stm32wbaxx_hal_conf_template.h - * @author MCD Application Team - * @brief HAL configuration template file. - * This file should be copied to the application folder and renamed - * to stm32wbaxx_hal_conf.h. - ****************************************************************************** - * @attention - * - * Copyright (c) 2022 STMicroelectronics. - * All rights reserved. - * - * This software is licensed under terms that can be found in the LICENSE file - * in the root directory of this software component. - * If no LICENSE file comes with this software, it is provided AS-IS. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef STM32WBAxx_HAL_CONF_H -#define STM32WBAxx_HAL_CONF_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ - -/* ########################## Module Selection ############################## */ -/** - * @brief This is the list of modules to be used in the HAL driver - */ -#define HAL_MODULE_ENABLED -#define HAL_ADC_MODULE_ENABLED -#define HAL_COMP_MODULE_ENABLED -#define HAL_CORTEX_MODULE_ENABLED -#define HAL_CRC_MODULE_ENABLED -#define HAL_CRYP_MODULE_ENABLED -#define HAL_DMA_MODULE_ENABLED -#define HAL_EXTI_MODULE_ENABLED -#define HAL_FLASH_MODULE_ENABLED -#define HAL_GPIO_MODULE_ENABLED -#define HAL_GTZC_MODULE_ENABLED -#define HAL_HASH_MODULE_ENABLED -#define HAL_HCD_MODULE_ENABLED -#define HAL_HSEM_MODULE_ENABLED -#define HAL_I2C_MODULE_ENABLED -#define HAL_ICACHE_MODULE_ENABLED -#define HAL_IRDA_MODULE_ENABLED -#define HAL_IWDG_MODULE_ENABLED -#define HAL_LPTIM_MODULE_ENABLED -#define HAL_PCD_MODULE_ENABLED -#define HAL_PKA_MODULE_ENABLED -#define HAL_PWR_MODULE_ENABLED -#define HAL_RAMCFG_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED -#define HAL_RNG_MODULE_ENABLED -#define HAL_RTC_MODULE_ENABLED -#define HAL_SAI_MODULE_ENABLED -#define HAL_SMARTCARD_MODULE_ENABLED -#define HAL_SMBUS_MODULE_ENABLED -#define HAL_SPI_MODULE_ENABLED -#define HAL_TIM_MODULE_ENABLED -#define HAL_TSC_MODULE_ENABLED -#define HAL_UART_MODULE_ENABLED -#define HAL_USART_MODULE_ENABLED -#define HAL_WWDG_MODULE_ENABLED -/* #define HAL_XSPI_MODULE_ENABLED */ - -/* ########################## Oscillator Values adaptation ####################*/ -/** - * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). - */ -#if !defined (HSE_VALUE) -#define HSE_VALUE 32000000UL /*!< Value of the External oscillator in Hz */ -#endif /* HSE_VALUE */ - -#if !defined (HSE_STARTUP_TIMEOUT) -#define HSE_STARTUP_TIMEOUT 100UL /*!< Time out for HSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief Internal High Speed oscillator (HSI) value. - * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). - */ -#if !defined (HSI_VALUE) -#define HSI_VALUE 16000000UL /*!< Value of the Internal oscillator in Hz*/ -#endif /* HSI_VALUE */ - -/** - * @brief Internal Low Speed oscillator (LSI) value. - */ -#if !defined (LSI_VALUE) -#define LSI_VALUE 32000UL /*!< LSI Typical Value in Hz*/ -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations in voltage - and temperature.*/ - -#if defined (RCC_LSI2_SUPPORT) -#if !defined (LSI2_VALUE) -#define LSI2_VALUE 32000UL /*!< LSI2 Typical Value in Hz*/ -#endif /* LSI2_VALUE */ -#endif - -/** - * @brief External Low Speed oscillator (LSE) value. - * This value is used by the UART, RTC HAL module to compute the system frequency - */ -#if !defined (LSE_VALUE) -#define LSE_VALUE 32768UL /*!< Value of the External oscillator in Hz*/ -#endif /* LSE_VALUE */ - -#if !defined (LSE_STARTUP_TIMEOUT) -#define LSE_STARTUP_TIMEOUT 5000UL /*!< Time out for LSE start up, in ms */ -#endif /* HSE_STARTUP_TIMEOUT */ - -/** - * @brief External clock source for SAI1 peripheral - * This value is used by the RCC HAL module to compute the SAI1 & SAI2 clock source - * frequency. - */ -#if !defined (EXTERNAL_SAI1_CLOCK_VALUE) -#define EXTERNAL_SAI1_CLOCK_VALUE 48000UL /*!< Value of the SAI1 External clock source in Hz*/ -#endif /* EXTERNAL_SAI1_CLOCK_VALUE */ - -/* Tip: To avoid modifying this file each time you need to use different HSE, - === you can define the HSE value in your toolchain compiler preprocessor. */ - -/* ########################### System Configuration ######################### */ -/** - * @brief This is the HAL system configuration section - */ -#define VDD_VALUE 3300UL /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY ((1UL<<__NVIC_PRIO_BITS) - 1UL) /*!< tick interrupt priority (lowest by default) */ -#define USE_RTOS 0U -#define PREFETCH_ENABLE 1U /*!< Enable prefetch */ - -/* ########################## Assert Selection ############################## */ -/** - * @brief Uncomment the line below to expanse the "assert_param" macro in the - * HAL drivers code - */ -/* #define USE_FULL_ASSERT 1U */ - -/* ################## Register callback feature configuration ############### */ -/** - * @brief Set below the peripheral configuration to "1U" to add the support - * of HAL callback registration/unregistration feature for the HAL - * driver(s). This allows user application to provide specific callback - * functions thanks to HAL_PPP_RegisterCallback() rather than overwriting - * the default weak callback functions (see each stm32wbaxx_hal_ppp.h file - * for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef - * for each PPP peripheral). - */ -#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ -#define USE_HAL_COMP_REGISTER_CALLBACKS 0U /* COMP register callback disabled */ -#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ -#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ -#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ -#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ -#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ -#define USE_HAL_IWDG_REGISTER_CALLBACKS 0U /* IWDG register callback disabled */ -#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ -#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ -#define USE_HAL_PKA_REGISTER_CALLBACKS 0U /* PKA register callback disabled */ -#define USE_HAL_RAMCFG_REGISTER_CALLBACKS 0U /* RAMCFG register callback disabled */ -#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ -#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ -#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ -#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ -#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ -#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ -#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ -#define USE_HAL_TSC_REGISTER_CALLBACKS 0U /* TSC register callback disabled */ -#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ -#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ -#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ -#define USE_HAL_XSPI_REGISTER_CALLBACKS 0U /* XSPI register callback disabled */ - -/* ################## SPI peripheral configuration ########################## */ - -/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver - * Activated: CRC code is present inside driver - * Deactivated: CRC code cleaned from driver - */ -#define USE_SPI_CRC 1U - -/* ################## CRYP peripheral configuration ########################## */ - -#define USE_HAL_CRYP_SUSPEND_RESUME 0U - -/* ################## HASH peripheral configuration ########################## */ - -#define USE_HAL_HASH_SUSPEND_RESUME 0U - -/* Includes ------------------------------------------------------------------*/ -/** - * @brief Include module's header file - */ -#ifdef HAL_DMA_MODULE_ENABLED -#include "stm32wbaxx_hal_dma.h" -#endif /* HAL_DMA_MODULE_ENABLED */ - -#ifdef HAL_RCC_MODULE_ENABLED -#include "stm32wbaxx_hal_rcc.h" -#endif /* HAL_RCC_MODULE_ENABLED */ - -#ifdef HAL_ADC_MODULE_ENABLED -#include "stm32wbaxx_hal_adc.h" -#endif /* HAL_ADC_MODULE_ENABLED */ - -#ifdef HAL_COMP_MODULE_ENABLED -#include "stm32wbaxx_hal_comp.h" -#endif /* HAL_COMP_MODULE_ENABLED */ - -#ifdef HAL_CORTEX_MODULE_ENABLED -#include "stm32wbaxx_hal_cortex.h" -#endif /* HAL_CORTEX_MODULE_ENABLED */ - -#ifdef HAL_CRC_MODULE_ENABLED -#include "stm32wbaxx_hal_crc.h" -#endif /* HAL_CRC_MODULE_ENABLED */ - -#ifdef HAL_CRYP_MODULE_ENABLED -#include "stm32wbaxx_hal_cryp.h" -#endif /* HAL_CRYP_MODULE_ENABLED */ - -#ifdef HAL_EXTI_MODULE_ENABLED -#include "stm32wbaxx_hal_exti.h" -#endif /* HAL_EXTI_MODULE_ENABLED */ - -#ifdef HAL_FLASH_MODULE_ENABLED -#include "stm32wbaxx_hal_flash.h" -#endif /* HAL_FLASH_MODULE_ENABLED */ - -#ifdef HAL_GPIO_MODULE_ENABLED -#include "stm32wbaxx_hal_gpio.h" -#endif /* HAL_GPIO_MODULE_ENABLED */ - -#ifdef HAL_GTZC_MODULE_ENABLED -#include "stm32wbaxx_hal_gtzc.h" -#endif /* HAL_GTZC_MODULE_ENABLED */ - -#ifdef HAL_HASH_MODULE_ENABLED -#include "stm32wbaxx_hal_hash.h" -#endif /* HAL_HASH_MODULE_ENABLED */ - -#ifdef HAL_HCD_MODULE_ENABLED -#include "stm32wbaxx_hal_hcd.h" -#endif /* HAL_HCD_MODULE_ENABLED */ - -#ifdef HAL_HSEM_MODULE_ENABLED -#include "stm32wbaxx_hal_hsem.h" -#endif /* HAL_HSEM_MODULE_ENABLED */ - -#ifdef HAL_I2C_MODULE_ENABLED -#include "stm32wbaxx_hal_i2c.h" -#endif /* HAL_I2C_MODULE_ENABLED */ - -#ifdef HAL_ICACHE_MODULE_ENABLED -#include "stm32wbaxx_hal_icache.h" -#endif /* HAL_ICACHE_MODULE_ENABLED */ - -#ifdef HAL_IRDA_MODULE_ENABLED -#include "stm32wbaxx_hal_irda.h" -#endif /* HAL_IRDA_MODULE_ENABLED */ - -#ifdef HAL_IWDG_MODULE_ENABLED -#include "stm32wbaxx_hal_iwdg.h" -#endif /* HAL_IWDG_MODULE_ENABLED */ - -#ifdef HAL_LPTIM_MODULE_ENABLED -#include "stm32wbaxx_hal_lptim.h" -#endif /* HAL_LPTIM_MODULE_ENABLED */ - -#ifdef HAL_PCD_MODULE_ENABLED -#include "stm32wbaxx_hal_pcd.h" -#endif /* HAL_PCD_MODULE_ENABLED */ - -#ifdef HAL_PKA_MODULE_ENABLED -#include "stm32wbaxx_hal_pka.h" -#endif /* HAL_PKA_MODULE_ENABLED */ - -#ifdef HAL_PWR_MODULE_ENABLED -#include "stm32wbaxx_hal_pwr.h" -#endif /* HAL_PWR_MODULE_ENABLED */ - -#ifdef HAL_RAMCFG_MODULE_ENABLED -#include "stm32wbaxx_hal_ramcfg.h" -#endif /* HAL_RAMCFG_MODULE_ENABLED */ - -#ifdef HAL_RNG_MODULE_ENABLED -#include "stm32wbaxx_hal_rng.h" -#endif /* HAL_RNG_MODULE_ENABLED */ - -#ifdef HAL_RTC_MODULE_ENABLED -#include "stm32wbaxx_hal_rtc.h" -#endif /* HAL_RTC_MODULE_ENABLED */ - -#ifdef HAL_SAI_MODULE_ENABLED -#include "stm32wbaxx_hal_sai.h" -#endif /* HAL_SAI_MODULE_ENABLED */ - -#ifdef HAL_SMARTCARD_MODULE_ENABLED -#include "stm32wbaxx_hal_smartcard.h" -#endif /* HAL_SMARTCARD_MODULE_ENABLED */ - -#ifdef HAL_SMBUS_MODULE_ENABLED -#include "stm32wbaxx_hal_smbus.h" -#endif /* HAL_SMBUS_MODULE_ENABLED */ - -#ifdef HAL_SPI_MODULE_ENABLED -#include "stm32wbaxx_hal_spi.h" -#endif /* HAL_SPI_MODULE_ENABLED */ - -#ifdef HAL_TIM_MODULE_ENABLED -#include "stm32wbaxx_hal_tim.h" -#endif /* HAL_TIM_MODULE_ENABLED */ - -#ifdef HAL_TSC_MODULE_ENABLED -#include "stm32wbaxx_hal_tsc.h" -#endif /* HAL_TSC_MODULE_ENABLED */ - -#ifdef HAL_UART_MODULE_ENABLED -#include "stm32wbaxx_hal_uart.h" -#endif /* HAL_UART_MODULE_ENABLED */ - -#ifdef HAL_USART_MODULE_ENABLED -#include "stm32wbaxx_hal_usart.h" -#endif /* HAL_USART_MODULE_ENABLED */ - -#ifdef HAL_WWDG_MODULE_ENABLED -#include "stm32wbaxx_hal_wwdg.h" -#endif /* HAL_WWDG_MODULE_ENABLED */ - -#ifdef HAL_XSPI_MODULE_ENABLED -/* #include "stm32wbaxx_hal_xspi.h" */ -#endif /* HAL_XSPI_MODULE_ENABLED */ - -/* Exported macro ------------------------------------------------------------*/ -#ifdef USE_FULL_ASSERT -/** - * @brief The assert_param macro is used for function's parameters check. - * @param expr: If expr is false, it calls assert_failed function - * which reports the name of the source file and the source - * line number of the call that failed. - * If expr is true, it returns no value. - * @retval None - */ -#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) -/* Exported functions ------------------------------------------------------- */ -void assert_failed(uint8_t *file, uint32_t line); -#else -#define assert_param(expr) ((void)0U) -#endif /* USE_FULL_ASSERT */ - -#ifdef __cplusplus -} -#endif - -#endif /* STM32WBAxx_HAL_CONF_H */ - diff --git a/hw/bsp/stm32wba/family.cmake b/hw/bsp/stm32wba/family.cmake new file mode 100644 index 000000000..3f41900ea --- /dev/null +++ b/hw/bsp/stm32wba/family.cmake @@ -0,0 +1,147 @@ +include_guard() + +set(ST_FAMILY wba) +set(ST_PREFIX stm32${ST_FAMILY}xx) + +set(ST_HAL_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver) +set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis_device_${ST_FAMILY}) +set(CMSIS_5 ${TOP}/lib/CMSIS_5) + +# include board specific +include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake) + +# toolchain set up +set(CMAKE_SYSTEM_CPU cortex-m33 CACHE INTERNAL "System Processor") +set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/arm_${TOOLCHAIN}.cmake) + +set(FAMILY_MCUS STM32WBA CACHE INTERNAL "") + +# ---------------------- +# Port & Speed Selection +# ---------------------- +if (NOT DEFINED RHPORT_DEVICE) + set(RHPORT_DEVICE 0) +endif () +if (NOT DEFINED RHPORT_HOST) + set(RHPORT_HOST 0) +endif () + +if (NOT DEFINED RHPORT_SPEED) + # WBA65/64/62 has built-in HS PHY + set(RHPORT_SPEED OPT_MODE_HIGH_SPEED OPT_MODE_HIGH_SPEED) +endif () +if (NOT DEFINED RHPORT_DEVICE_SPEED) + list(GET RHPORT_SPEED ${RHPORT_DEVICE} RHPORT_DEVICE_SPEED) +endif () +if (NOT DEFINED RHPORT_HOST_SPEED) + list(GET RHPORT_SPEED ${RHPORT_HOST} RHPORT_HOST_SPEED) +endif () + +cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) + +#------------------------------------ +# BOARD_TARGET +#------------------------------------ +# only need to be built ONCE for all examples +function(add_board_target BOARD_TARGET) + if (TARGET ${BOARD_TARGET}) + return() + endif() + + # STM32WBA HAL uses uppercase MCU_VARIANT (excluding the x's) for linking and lowercase MCU_VARIANT for startup. + string(TOUPPER "${MCU_VARIANT}" UPPERCASE_MCU_VARIANT) + string(REGEX REPLACE "X" "x" UPPERCASE_MCU_VARIANT "${UPPERCASE_MCU_VARIANT}") + + # Startup & Linker script + set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s) + set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) + set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) + + set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/${UPPERCASE_MCU_VARIANT}_FLASH_ns.ld) + set(LD_FILE_Clang ${LD_FILE_GNU}) + set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash_ns.icf) + + add_library(${BOARD_TARGET} STATIC + ${ST_CMSIS}/Source/Templates/system_${ST_PREFIX}.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_icache.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pcd.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pcd_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_ll_usb.c + ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} + ) + target_include_directories(${BOARD_TARGET} PUBLIC + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMSIS_5}/CMSIS/Core/Include + ${ST_CMSIS}/Include + ${ST_HAL_DRIVER}/Inc + ) + + update_board(${BOARD_TARGET}) + + if (CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_GNU}" + -nostartfiles + --specs=nosys.specs --specs=nano.specs + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--script=${LD_FILE_Clang}" + ) + elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR") + target_link_options(${BOARD_TARGET} PUBLIC + "LINKER:--config=${LD_FILE_IAR}" + ) + endif () +endfunction() + + +#------------------------------------ +# Functions +#------------------------------------ +function(family_configure_example TARGET RTOS) + family_configure_common(${TARGET} ${RTOS}) + + target_compile_definitions(${TARGET} PUBLIC + CFG_TUSB_MCU=OPT_MCU_STM32WBA + ) + + # Board target + add_board_target(board_${BOARD}) + + #---------- Port Specific ---------- + # These files are built for each example since it depends on example's tusb_config.h + target_sources(${TARGET} PUBLIC + # BSP + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c + ) + target_include_directories(${TARGET} PUBLIC + # family, hw, board + ${CMAKE_CURRENT_FUNCTION_LIST_DIR} + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../../ + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/boards/${BOARD} + ) + + # Add TinyUSB target and port source + family_add_tinyusb(${TARGET} OPT_MCU_STM32WBA) + target_sources(${TARGET} PUBLIC + ${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c + ${TOP}/src/portable/synopsys/dwc2/dwc2_common.c + ) + target_link_libraries(${TARGET} PUBLIC board_${BOARD}) + + # Flashing + family_add_bin_hex(${TARGET}) + family_flash_stlink(${TARGET}) + family_flash_jlink(${TARGET}) +endfunction() diff --git a/hw/bsp/stm32wba/family.mk b/hw/bsp/stm32wba/family.mk index ca6459ab2..b07769624 100644 --- a/hw/bsp/stm32wba/family.mk +++ b/hw/bsp/stm32wba/family.mk @@ -34,8 +34,7 @@ SRC_C += \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_gpio.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pcd.c \ $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_pcd_ex.c \ - $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_ll_usb.c \ - $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal.c + $(ST_HAL_DRIVER)/Src/${ST_PREFIX}_ll_usb.c INC += \ $(TOP)/$(BOARD_PATH) \ @@ -53,7 +52,7 @@ SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT).s # Linker LD_FILE_GCC ?= ${ST_CMSIS}/Source/Templates/gcc/linker/${UPPERCASE_MCU_VARIANT}_FLASH_ns.ld -LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash_cm33.icf +LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash_ns.icf # flash target using on-board stlink flash: flash-stlink \ No newline at end of file From c9527bc0964dcd883df7ec485e2d71333ed780c0 Mon Sep 17 00:00:00 2001 From: Dalton Caron Date: Wed, 10 Sep 2025 11:14:52 -0700 Subject: [PATCH 363/382] Bring up to date with master --- src/portable/synopsys/dwc2/dwc2_stm32.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/portable/synopsys/dwc2/dwc2_stm32.h b/src/portable/synopsys/dwc2/dwc2_stm32.h index ca5ce5a7c..08950ccc0 100644 --- a/src/portable/synopsys/dwc2/dwc2_stm32.h +++ b/src/portable/synopsys/dwc2/dwc2_stm32.h @@ -249,14 +249,11 @@ static inline void dwc2_phy_init(dwc2_regs_t* dwc2, uint8_t hs_phy_type) { // Enable PLL internal PHY USB_HS_PHYC->USB_HS_PHYC_PLL |= USB_HS_PHYC_PLL_PLLEN; -<<<<<<< HEAD // Wait ~2ms until the PLL is ready (there's no RDY bit to query) tusb_time_delay_ms_api(2); #else -======= ->>>>>>> 246a92c65 (It worksgit status!) #endif } } From 9cde80f82351268fc1238e9f21c16ec2379d0ce4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Sep 2025 10:37:19 +0700 Subject: [PATCH 364/382] fix pre-commit --- hw/bsp/stm32wba/family.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/stm32wba/family.mk b/hw/bsp/stm32wba/family.mk index b07769624..d5aecfe46 100644 --- a/hw/bsp/stm32wba/family.mk +++ b/hw/bsp/stm32wba/family.mk @@ -55,4 +55,4 @@ LD_FILE_GCC ?= ${ST_CMSIS}/Source/Templates/gcc/linker/${UPPERCASE_MCU_VARIANT}_ LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash_ns.icf # flash target using on-board stlink -flash: flash-stlink \ No newline at end of file +flash: flash-stlink From 5e661eac8809f3bfdafd357d00013d94b71b4000 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Sep 2025 10:57:02 +0700 Subject: [PATCH 365/382] Revert "Incorporate upstream changes to dwc2_common.c" This reverts commit 48f6b95bd8b0c3d33832f289b02b53da410d5ef9. also revert gsnpsid shadown since it is already in the upstream --- src/portable/synopsys/dwc2/dwc2_common.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index 9b8333ad2..d7d157149 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -95,6 +95,14 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; const dwc2_ghwcfg4_t ghwcfg4 = {.value = dwc2->ghwcfg4}; + uint8_t phy_width; + if (CFG_TUSB_MCU != OPT_MCU_AT32F402_405 && // at32f402_405 does not support 16-bit + ghwcfg4.phy_data_width) { + phy_width = 16; // 16-bit PHY interface if supported + } else { + phy_width = 8; // 8-bit PHY interface + } + // De-select FS PHY gusbcfg &= ~GUSBCFG_PHYSEL; @@ -122,12 +130,10 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { gusbcfg &= ~GUSBCFG_ULPI_UTMI_SEL; // Set 16-bit interface if supported - if (ghwcfg4.phy_data_width) { - #if CFG_TUSB_MCU != OPT_MCU_AT32F402_405 // at32f402_405 does not actually support 16-bit - gusbcfg |= GUSBCFG_PHYIF16; // 16 bit - #endif + if (phy_width == 16) { + gusbcfg |= GUSBCFG_PHYIF16; } else { - gusbcfg &= ~GUSBCFG_PHYIF16; // 8 bit + gusbcfg &= ~GUSBCFG_PHYIF16; } } @@ -144,13 +150,7 @@ static void phy_hs_init(dwc2_regs_t* dwc2) { // - 9 if using 8-bit PHY interface // - 5 if using 16-bit PHY interface gusbcfg &= ~GUSBCFG_TRDT_Msk; - -#if CFG_TUSB_MCU == OPT_MCU_AT32F402_405 // at32f402_405 does not actually support 16-bit - gusbcfg |= 9u << GUSBCFG_TRDT_Pos; -#else - gusbcfg |= (dwc2->ghwcfg4_bm.phy_data_width ? 5u : 9u) << GUSBCFG_TRDT_Pos; -#endif - + gusbcfg |= (phy_width == 16 ? 5u : 9u) << GUSBCFG_TRDT_Pos; dwc2->gusbcfg = gusbcfg; // MCU specific PHY update post reset From 040d1b43f103eb218e526dbd31e06505e5163578 Mon Sep 17 00:00:00 2001 From: Dalton Caron Date: Thu, 11 Sep 2025 09:09:16 -0700 Subject: [PATCH 366/382] Make get_deps.py WBA definition consistent with upstream and other defs --- tools/get_deps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/get_deps.py b/tools/get_deps.py index 37d541785..282331f82 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -130,7 +130,7 @@ deps_optional = { 'hw/mcu/st/cmsis_device_wb': ['https://github.com/STMicroelectronics/cmsis_device_wb.git', 'cda2cb9fc4a5232ab18efece0bb06b0b60910083', 'stm32wb'], - 'hw/mcu/st/cmsis_device_wba': ['https://github.com/STMicroelectronics/cmsis-device-wba', + 'hw/mcu/st/cmsis-device-wba': ['https://github.com/STMicroelectronics/cmsis-device-wba.git', '647d8522e5fd15049e9a1cc30ed19d85e5911eaf', 'stm32wba'], 'hw/mcu/st/stm32-mfxstm32l152': ['https://github.com/STMicroelectronics/stm32-mfxstm32l152.git', From af7310b925c031d23ba490e8f70965f345da1a4d Mon Sep 17 00:00:00 2001 From: Dalton Caron Date: Thu, 11 Sep 2025 09:13:54 -0700 Subject: [PATCH 367/382] Revert fsdev_stm32.h changes --- src/portable/st/stm32_fsdev/fsdev_stm32.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 01baf50ae..ccf31e035 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -148,12 +148,6 @@ /* ST provided header has incorrect value of USB_PMAADDR */ #define FSDEV_PMA_BASE USB1_PMAADDR -#elif defined(STM32WBA62xx) || defined(STM32WBA64xx) || defined(STM32WBA65xx) - // Available only on STM32WBA62/64/65xx devices - #include "stm32wbaxx.h" - #define FSDEV_PMA_SIZE (2048u) - #define USB USB_DRD_FS - #elif CFG_TUSB_MCU == OPT_MCU_STM32L4 #include "stm32l4xx.h" #define FSDEV_PMA_SIZE (1024u) @@ -295,8 +289,6 @@ static const IRQn_Type fsdev_irq[] = { USB_LP_IRQn, #elif CFG_TUSB_MCU == OPT_MCU_STM32U5 USB_IRQn, - #elif CFG_TUSB_MCU == OPT_MCU_STM32WBA - USB_OTG_HS_IRQn, #elif CFG_TUSB_MCU == OPT_MCU_STM32U0 USB_DRD_FS_IRQn, #else From e09a2d8d356bd1165a4474f5de7dce43c936cb2e Mon Sep 17 00:00:00 2001 From: Dalton Caron Date: Thu, 11 Sep 2025 13:00:48 -0700 Subject: [PATCH 368/382] Change CMSIS patch to match update path in family.mk for WBA --- hw/bsp/stm32wba/family.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/stm32wba/family.mk b/hw/bsp/stm32wba/family.mk index d5aecfe46..22f63609f 100644 --- a/hw/bsp/stm32wba/family.mk +++ b/hw/bsp/stm32wba/family.mk @@ -2,7 +2,7 @@ UF2_FAMILY_ID = 0x70d16657 ST_FAMILY = wba ST_PREFIX = stm32${ST_FAMILY}xx -ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY) +ST_CMSIS = hw/mcu/st/cmsis-device-$(ST_FAMILY) ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver include $(TOP)/$(BOARD_PATH)/board.mk From 913597707493ed7ac075d420795574bc7faa3075 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 12 Sep 2025 11:26:16 +0700 Subject: [PATCH 369/382] rename stm32wba eval to nucleo use local linker to fix READONLY keyword with clang add wba to ci build --- .github/workflows/ci_set_matrix.py | 1 + docs/reference/dependencies.rst | 81 +++--- .../board.cmake | 0 .../board.h | 0 .../board.mk | 0 hw/bsp/stm32wba/family.c | 271 ++++++++---------- hw/bsp/stm32wba/family.cmake | 45 ++- hw/bsp/stm32wba/family.mk | 9 +- .../stm32wba/linker/STM32WBA65xx_FLASH_ns.ld | 188 ++++++++++++ 9 files changed, 378 insertions(+), 217 deletions(-) rename hw/bsp/stm32wba/boards/{stm32wba_eval => stm32wba_nucleo}/board.cmake (100%) rename hw/bsp/stm32wba/boards/{stm32wba_eval => stm32wba_nucleo}/board.h (100%) rename hw/bsp/stm32wba/boards/{stm32wba_eval => stm32wba_nucleo}/board.mk (100%) create mode 100644 hw/bsp/stm32wba/linker/STM32WBA65xx_FLASH_ns.ld diff --git a/.github/workflows/ci_set_matrix.py b/.github/workflows/ci_set_matrix.py index 40d51a7a2..3559909ba 100755 --- a/.github/workflows/ci_set_matrix.py +++ b/.github/workflows/ci_set_matrix.py @@ -45,6 +45,7 @@ family_list = { "stm32l0 stm32l4": ["arm-gcc", "arm-clang", "arm-iar"], "stm32n6": ["arm-gcc"], "stm32u5 stm32wb": ["arm-gcc", "arm-clang", "arm-iar"], + "stm32wba": ["arm-gcc", "arm-clang"], "xmc4000": ["arm-gcc"], "-bespressif_s2_devkitc": ["esp-idf"], # S3, P4 will be built by hil test diff --git a/docs/reference/dependencies.rst b/docs/reference/dependencies.rst index 8a65eee86..ca5c84151 100644 --- a/docs/reference/dependencies.rst +++ b/docs/reference/dependencies.rst @@ -26,52 +26,53 @@ hw/mcu/nordic/nrfx https://github.com/NordicSemiconductor hw/mcu/nuvoton https://github.com/majbthrd/nuc_driver.git 2204191ec76283371419fbcec207da02e1bc22fa nuc hw/mcu/nxp/lpcopen https://github.com/hathach/nxp_lpcopen.git b41cf930e65c734d8ec6de04f1d57d46787c76ae lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 hw/mcu/nxp/mcux-sdk https://github.com/nxp-mcuxpresso/mcux-sdk a1bdae309a14ec95a4f64a96d3315a4f89c397c6 kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt -hw/mcu/raspberry_pi/Pico-PIO-USB https://github.com/sekigon-gonnoc/Pico-PIO-USB.git 3c1eec341a5232640e4c00628b889b641af34b28 rp2040 +hw/mcu/raspberry_pi/Pico-PIO-USB https://github.com/sekigon-gonnoc/Pico-PIO-USB.git 675543bcc9baa8170f868ab7ba316d418dbcf41f rp2040 hw/mcu/renesas/fsp https://github.com/renesas/fsp.git edcc97d684b6f716728a60d7a6fea049d9870bd6 ra hw/mcu/renesas/rx https://github.com/kkitayam/rx_device.git 706b4e0cf485605c32351e2f90f5698267996023 rx hw/mcu/silabs/cmsis-dfp-efm32gg12b https://github.com/cmsis-packs/cmsis-dfp-efm32gg12b.git f1c31b7887669cb230b3ea63f9b56769078960bc efm32 hw/mcu/sony/cxd56/spresense-exported-sdk https://github.com/sonydevworld/spresense-exported-sdk.git 2ec2a1538362696118dc3fdf56f33dacaf8f4067 spresense -hw/mcu/st/cmsis_device_c0 https://github.com/STMicroelectronics/cmsis_device_c0.git fb56b1b70c73b74eacda2a4bcc36886444364ab3 stm32c0 -hw/mcu/st/cmsis_device_f0 https://github.com/STMicroelectronics/cmsis_device_f0.git 2fc25ee22264bc27034358be0bd400b893ef837e stm32f0 -hw/mcu/st/cmsis_device_f1 https://github.com/STMicroelectronics/cmsis_device_f1.git 6601104a6397299b7304fd5bcd9a491f56cb23a6 stm32f1 -hw/mcu/st/cmsis_device_f2 https://github.com/STMicroelectronics/cmsis_device_f2.git 182fcb3681ce116816feb41b7764f1b019ce796f stm32f2 -hw/mcu/st/cmsis_device_f3 https://github.com/STMicroelectronics/cmsis_device_f3.git 5e4ee5ed7a7b6c85176bb70a9fd3c72d6eb99f1b stm32f3 -hw/mcu/st/cmsis_device_f4 https://github.com/STMicroelectronics/cmsis_device_f4.git 2615e866fa48fe1ff1af9e31c348813f2b19e7ec stm32f4 -hw/mcu/st/cmsis_device_f7 https://github.com/STMicroelectronics/cmsis_device_f7.git 25b0463439303b7a38f0d27b161f7d2f3c096e79 stm32f7 -hw/mcu/st/cmsis_device_g0 https://github.com/STMicroelectronics/cmsis_device_g0.git 3a23e1224417f3f2d00300ecd620495e363f2094 stm32g0 -hw/mcu/st/cmsis_device_g4 https://github.com/STMicroelectronics/cmsis_device_g4.git ce822adb1dc552b3aedd13621edbc7fdae124878 stm32g4 -hw/mcu/st/cmsis_device_h5 https://github.com/STMicroelectronics/cmsis_device_h5.git cd2d1d579743de57b88ccaf61a968b9c05848ffc stm32h5 -hw/mcu/st/cmsis_device_h7 https://github.com/STMicroelectronics/cmsis_device_h7.git 60dc2c913203dc8629dc233d4384dcc41c91e77f stm32h7 -hw/mcu/st/cmsis_device_h7rs https://github.com/STMicroelectronics/cmsis_device_h7rs.git 832649d1fd09bd901e9f68e979522e5c209ebf20 stm32h7rs -hw/mcu/st/cmsis_device_l0 https://github.com/STMicroelectronics/cmsis_device_l0.git 69cd5999fd40ae6e546d4905b21635c6ca1bcb92 stm32l0 -hw/mcu/st/cmsis_device_l1 https://github.com/STMicroelectronics/cmsis_device_l1.git 7f16ec0a1c4c063f84160b4cc6bf88ad554a823e stm32l1 -hw/mcu/st/cmsis_device_l4 https://github.com/STMicroelectronics/cmsis_device_l4.git 6ca7312fa6a5a460b5a5a63d66da527fdd8359a6 stm32l4 -hw/mcu/st/cmsis_device_l5 https://github.com/STMicroelectronics/cmsis_device_l5.git d922865fc0326a102c26211c44b8e42f52c1e53d stm32l5 -hw/mcu/st/cmsis_device_n6 https://github.com/STMicroelectronics/cmsis-device-n6.git f818b00f775444e8d19ef6cad822534c345e054f stm32n6 -hw/mcu/st/cmsis_device_u5 https://github.com/STMicroelectronics/cmsis_device_u5.git 5ad9797c54ec3e55eff770fc9b3cd4a1aefc1309 stm32u5 -hw/mcu/st/cmsis_device_wb https://github.com/STMicroelectronics/cmsis_device_wb.git d6a7fa2e7de084f5e5e47f2ab88b022fe9b50e5a stm32wb +hw/mcu/st/cmsis-device-wba https://github.com/STMicroelectronics/cmsis-device-wba.git 647d8522e5fd15049e9a1cc30ed19d85e5911eaf stm32wba +hw/mcu/st/cmsis_device_c0 https://github.com/STMicroelectronics/cmsis_device_c0.git 517611273f835ffe95318947647bc1408f69120d stm32c0 +hw/mcu/st/cmsis_device_f0 https://github.com/STMicroelectronics/cmsis_device_f0.git cbb5da5d48b4b5f2efacdc2f033be30f9d29889f stm32f0 +hw/mcu/st/cmsis_device_f1 https://github.com/STMicroelectronics/cmsis_device_f1.git c8e9a4a4f16b6d2cb2a2083cbe5161025280fb22 stm32f1 +hw/mcu/st/cmsis_device_f2 https://github.com/STMicroelectronics/cmsis_device_f2.git 49321f1e4d2bd3e65687b37f2652a28ea7983674 stm32f2 +hw/mcu/st/cmsis_device_f3 https://github.com/STMicroelectronics/cmsis_device_f3.git 5558e64e3675a1e1fcb1c71f468c7c407c1b1134 stm32f3 +hw/mcu/st/cmsis_device_f4 https://github.com/STMicroelectronics/cmsis_device_f4.git 3c77349ce04c8af401454cc51f85ea9a50e34fc1 stm32f4 +hw/mcu/st/cmsis_device_f7 https://github.com/STMicroelectronics/cmsis_device_f7.git 2352e888e821aa0f4fe549bd5ea81d29c67a3222 stm32f7 +hw/mcu/st/cmsis_device_g0 https://github.com/STMicroelectronics/cmsis_device_g0.git f484fe852535f913a02ee79787eafa74dd7f9488 stm32g0 +hw/mcu/st/cmsis_device_g4 https://github.com/STMicroelectronics/cmsis_device_g4.git 7c39c32593b03764aaa57531588b8bf7cdd443a5 stm32g4 +hw/mcu/st/cmsis_device_h5 https://github.com/STMicroelectronics/cmsis_device_h5.git 5273b8f134ba65f5b8174c4141b711b5c0d295b2 stm32h5 +hw/mcu/st/cmsis_device_h7 https://github.com/STMicroelectronics/cmsis_device_h7.git 45b818cab6ee2806e3a27c80e330957223424392 stm32h7 +hw/mcu/st/cmsis_device_h7rs https://github.com/STMicroelectronics/cmsis_device_h7rs.git 57ea11f70ebf1850e1048989d665c9070f0bb863 stm32h7rs +hw/mcu/st/cmsis_device_l0 https://github.com/STMicroelectronics/cmsis_device_l0.git 7b7ae8cd71437331e1d7824f157d00c7bb4a5044 stm32l0 +hw/mcu/st/cmsis_device_l1 https://github.com/STMicroelectronics/cmsis_device_l1.git a23ade4ccf14012085fedf862e33a536ab7ed8be stm32l1 +hw/mcu/st/cmsis_device_l4 https://github.com/STMicroelectronics/cmsis_device_l4.git a2530753e86dd326a75467d28feb92e2ba7d0df2 stm32l4 +hw/mcu/st/cmsis_device_l5 https://github.com/STMicroelectronics/cmsis_device_l5.git 7d9a51481f0e6c376e62c3c849e6caf652c66482 stm32l5 +hw/mcu/st/cmsis_device_n6 https://github.com/STMicroelectronics/cmsis-device-n6.git 7bcdc944fbf7cf5928d3c1d14054ca13261d33ec stm32n6 +hw/mcu/st/cmsis_device_u5 https://github.com/STMicroelectronics/cmsis_device_u5.git 6e67187dec98035893692ab2923914cb5f4e0117 stm32u5 +hw/mcu/st/cmsis_device_wb https://github.com/STMicroelectronics/cmsis_device_wb.git cda2cb9fc4a5232ab18efece0bb06b0b60910083 stm32wb hw/mcu/st/stm32-mfxstm32l152 https://github.com/STMicroelectronics/stm32-mfxstm32l152.git 7f4389efee9c6a655b55e5df3fceef5586b35f9b stm32h7 hw/mcu/st/stm32-tcpp0203 https://github.com/STMicroelectronics/stm32-tcpp0203.git 9918655bff176ac3046ccf378b5c7bbbc6a38d15 stm32h7rs stm32n6 -hw/mcu/st/stm32c0xx_hal_driver https://github.com/STMicroelectronics/stm32c0xx_hal_driver.git 41253e2f1d7ae4a4d0c379cf63f5bcf71fcf8eb3 stm32c0 -hw/mcu/st/stm32f0xx_hal_driver https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git 0e95cd88657030f640a11e690a8a5186c7712ea5 stm32f0 -hw/mcu/st/stm32f1xx_hal_driver https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git 1dd9d3662fb7eb2a7f7d3bc0a4c1dc7537915a29 stm32f1 -hw/mcu/st/stm32f2xx_hal_driver https://github.com/STMicroelectronics/stm32f2xx_hal_driver.git c75ace9b908a9aca631193ebf2466963b8ea33d0 stm32f2 -hw/mcu/st/stm32f3xx_hal_driver https://github.com/STMicroelectronics/stm32f3xx_hal_driver.git 1761b6207318ede021706e75aae78f452d72b6fa stm32f3 -hw/mcu/st/stm32f4xx_hal_driver https://github.com/STMicroelectronics/stm32f4xx_hal_driver.git 04e99fbdabd00ab8f370f377c66b0a4570365b58 stm32f4 -hw/mcu/st/stm32f7xx_hal_driver https://github.com/STMicroelectronics/stm32f7xx_hal_driver.git f7ffdf6bf72110e58b42c632b0a051df5997e4ee stm32f7 -hw/mcu/st/stm32g0xx_hal_driver https://github.com/STMicroelectronics/stm32g0xx_hal_driver.git e911b12c7f67084d7f6b76157a4c0d4e2ec3779c stm32g0 -hw/mcu/st/stm32g4xx_hal_driver https://github.com/STMicroelectronics/stm32g4xx_hal_driver.git 8b4518417706d42eef5c14e56a650005abf478a8 stm32g4 -hw/mcu/st/stm32h5xx_hal_driver https://github.com/STMicroelectronics/stm32h5xx_hal_driver.git 2cf77de584196d619cec1b4586c3b9e2820a254e stm32h5 -hw/mcu/st/stm32h7rsxx_hal_driver https://github.com/STMicroelectronics/stm32h7rsxx-hal-driver.git 7ca2e07ca21bc66b53654e845b4c85c884343b60 stm32h7rs -hw/mcu/st/stm32h7xx_hal_driver https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git d8461b980b59b1625207d8c4f2ce0a9c2a7a3b04 stm32h7 -hw/mcu/st/stm32l0xx_hal_driver https://github.com/STMicroelectronics/stm32l0xx_hal_driver.git fbdacaf6f8c82a4e1eb9bd74ba650b491e97e17b stm32l0 -hw/mcu/st/stm32l1xx_hal_driver https://github.com/STMicroelectronics/stm32l1xx_hal_driver.git 44efc446fa69ed8344e7fd966e68ed11043b35d9 stm32l1 -hw/mcu/st/stm32l4xx_hal_driver https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git aee3d5bf283ae5df87532b781bdd01b7caf256fc stm32l4 -hw/mcu/st/stm32l5xx_hal_driver https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git 675c32a75df37f39d50d61f51cb0dcf53f07e1cb stm32l5 -hw/mcu/st/stm32n6xx_hal_driver https://github.com/STMicroelectronics/stm32n6xx-hal-driver.git 49f9989d10cf6817d4b07ac01848956b46bd0fd6 stm32n6 -hw/mcu/st/stm32u5xx_hal_driver https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git 4d93097a67928e9377e655ddd14622adc31b9770 stm32u5 -hw/mcu/st/stm32wbxx_hal_driver https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git 2c5f06638be516c1b772f768456ba637f077bac8 stm32wb -hw/mcu/st/stm32wbaxx_hal_driver https://github.com/STMicroelectronics/stm32wbaxx-hal-driver.git 9442fbb71f855ff2e64fbf662b7726beba511a24 stm32wba +hw/mcu/st/stm32c0xx_hal_driver https://github.com/STMicroelectronics/stm32c0xx_hal_driver.git c283b143bef6bdaacf64240ee6f15eb61dad6125 stm32c0 +hw/mcu/st/stm32f0xx_hal_driver https://github.com/STMicroelectronics/stm32f0xx_hal_driver.git 94399697cb5eeaf8511b81b7f50dc62f0a5a3f6c stm32f0 +hw/mcu/st/stm32f1xx_hal_driver https://github.com/STMicroelectronics/stm32f1xx_hal_driver.git 18074e3e5ecad0b380a5cf5a9131fe4b5ed1b2b7 stm32f1 +hw/mcu/st/stm32f2xx_hal_driver https://github.com/STMicroelectronics/stm32f2xx_hal_driver.git ae7b47fe41cf75ccaf65cbf8ee8749b18ba0e0f3 stm32f2 +hw/mcu/st/stm32f3xx_hal_driver https://github.com/STMicroelectronics/stm32f3xx_hal_driver.git e098c8c8ce6f426bcee7db3a37c0932ea881eb0b stm32f3 +hw/mcu/st/stm32f4xx_hal_driver https://github.com/STMicroelectronics/stm32f4xx_hal_driver.git b6f0ed3829f3829eb358a2e7417d80bba1a42db7 stm32f4 +hw/mcu/st/stm32f7xx_hal_driver https://github.com/STMicroelectronics/stm32f7xx_hal_driver.git e1446fa12ffda80ea1016faf349e45b2047fff12 stm32f7 +hw/mcu/st/stm32g0xx_hal_driver https://github.com/STMicroelectronics/stm32g0xx_hal_driver.git a248a9e484d58943b46c68f6c49b4b276778bd59 stm32g0 +hw/mcu/st/stm32g4xx_hal_driver https://github.com/STMicroelectronics/stm32g4xx_hal_driver.git 10138a41749ea62d53ecab65b2bc2a950acc04d2 stm32g4 +hw/mcu/st/stm32h5xx_hal_driver https://github.com/STMicroelectronics/stm32h5xx_hal_driver.git 3c84eaa6000ab620be01afbcfba2735389afe09b stm32h5 +hw/mcu/st/stm32h7rsxx_hal_driver https://github.com/STMicroelectronics/stm32h7rsxx-hal-driver.git 9e83b95ae0f70faa067eddce2da617d180937f9b stm32h7rs +hw/mcu/st/stm32h7xx_hal_driver https://github.com/STMicroelectronics/stm32h7xx_hal_driver.git dbfb749f229e1aa89e50b54229ca87766e180d2d stm32h7 +hw/mcu/st/stm32l0xx_hal_driver https://github.com/STMicroelectronics/stm32l0xx_hal_driver.git 65da4cd8a10ad859ec8d9cd71f3f6c50735bd473 stm32l0 +hw/mcu/st/stm32l1xx_hal_driver https://github.com/STMicroelectronics/stm32l1xx_hal_driver.git 54f0b7568ce2acb33d090c70c897ee32229c1d32 stm32l1 +hw/mcu/st/stm32l4xx_hal_driver https://github.com/STMicroelectronics/stm32l4xx_hal_driver.git 3e039bbf62f54bbd834d578185521cff80596efe stm32l4 +hw/mcu/st/stm32l5xx_hal_driver https://github.com/STMicroelectronics/stm32l5xx_hal_driver.git 3340b9a597bcf75cc173345a90a74aa2a4a37510 stm32l5 +hw/mcu/st/stm32n6xx_hal_driver https://github.com/STMicroelectronics/stm32n6xx-hal-driver.git bc6c41f8f67d61b47af26695d0bf67762a000666 stm32n6 +hw/mcu/st/stm32u5xx_hal_driver https://github.com/STMicroelectronics/stm32u5xx_hal_driver.git 2c5e2568fbdb1900a13ca3b2901fdd302cac3444 stm32u5 +hw/mcu/st/stm32wbaxx_hal_driver https://github.com/STMicroelectronics/stm32wbaxx_hal_driver.git 9442fbb71f855ff2e64fbf662b7726beba511a24 stm32wba +hw/mcu/st/stm32wbxx_hal_driver https://github.com/STMicroelectronics/stm32wbxx_hal_driver.git d60dd46996876506f1d2e9abd6b1cc110c8004cd stm32wb hw/mcu/ti https://github.com/hathach/ti_driver.git 143ed6cc20a7615d042b03b21e070197d473e6e5 msp430 msp432e4 tm4c hw/mcu/wch/ch32f20x https://github.com/openwch/ch32f20x.git 77c4095087e5ed2c548ec9058e655d0b8757663b ch32f20x hw/mcu/wch/ch32v103 https://github.com/openwch/ch32v103.git 7578cae0b21f86dd053a1f781b2fc6ab99d0ec17 ch32v10x diff --git a/hw/bsp/stm32wba/boards/stm32wba_eval/board.cmake b/hw/bsp/stm32wba/boards/stm32wba_nucleo/board.cmake similarity index 100% rename from hw/bsp/stm32wba/boards/stm32wba_eval/board.cmake rename to hw/bsp/stm32wba/boards/stm32wba_nucleo/board.cmake diff --git a/hw/bsp/stm32wba/boards/stm32wba_eval/board.h b/hw/bsp/stm32wba/boards/stm32wba_nucleo/board.h similarity index 100% rename from hw/bsp/stm32wba/boards/stm32wba_eval/board.h rename to hw/bsp/stm32wba/boards/stm32wba_nucleo/board.h diff --git a/hw/bsp/stm32wba/boards/stm32wba_eval/board.mk b/hw/bsp/stm32wba/boards/stm32wba_nucleo/board.mk similarity index 100% rename from hw/bsp/stm32wba/boards/stm32wba_eval/board.mk rename to hw/bsp/stm32wba/boards/stm32wba_nucleo/board.mk diff --git a/hw/bsp/stm32wba/family.c b/hw/bsp/stm32wba/family.c index bacac2fdc..923ea197c 100644 --- a/hw/bsp/stm32wba/family.c +++ b/hw/bsp/stm32wba/family.c @@ -23,19 +23,20 @@ * * This file is part of the TinyUSB stack. */ + +/* metadata: + manufacturer: STMicroelectronics +*/ + #include #include "stm32wbaxx_hal.h" #include "bsp/board_api.h" #include "board.h" - //--------------------------------------------------------------------+ - // MACRO TYPEDEF CONSTANT ENUM - //--------------------------------------------------------------------+ -#ifndef CFG_BOARD_UART_BAUDRATE -#define CFG_BOARD_UART_BAUDRATE 115200 -#endif - +//--------------------------------------------------------------------+ +// MACRO TYPEDEF CONSTANT ENUM +//--------------------------------------------------------------------+ #ifndef USART_TIMEOUT_TICKS #define USART_TIMEOUT_TICKS 1000 #endif @@ -45,189 +46,171 @@ static UART_HandleTypeDef uart_handle; //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler //--------------------------------------------------------------------+ -void USB_OTG_HS_IRQHandler( void ) -{ - tud_int_handler( 0 ); +void USB_OTG_HS_IRQHandler(void) { + tud_int_handler(0); } //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ -static void board_gpio_configuration( void ) -{ - GPIO_InitTypeDef gpio_init = { 0 }; +static void board_gpio_configuration(void) { + GPIO_InitTypeDef gpio_init = {0}; - USART_GPIO_CLK_EN(); - USART_CLK_EN(); + USART_GPIO_CLK_EN(); + USART_CLK_EN(); - // Configure USART TX pin - gpio_init.Pin = USART_TX_PIN; - gpio_init.Mode = GPIO_MODE_AF_PP; - gpio_init.Pull = GPIO_NOPULL; - gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; - gpio_init.Alternate = USART_GPIO_AF; - HAL_GPIO_Init( USART_TX_GPIO_PORT, &gpio_init ); + // Configure USART TX pin + gpio_init.Pin = USART_TX_PIN; + gpio_init.Mode = GPIO_MODE_AF_PP; + gpio_init.Pull = GPIO_NOPULL; + gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; + gpio_init.Alternate = USART_GPIO_AF; + HAL_GPIO_Init(USART_TX_GPIO_PORT, &gpio_init); - // Configure USART RX pin - gpio_init.Pin = USART_RX_PIN; - gpio_init.Mode = GPIO_MODE_AF_PP; - gpio_init.Pull = GPIO_PULLUP; - gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; - gpio_init.Alternate = USART_GPIO_AF; - HAL_GPIO_Init( USART_RX_GPIO_PORT, &gpio_init ); + // Configure USART RX pin + gpio_init.Pin = USART_RX_PIN; + gpio_init.Mode = GPIO_MODE_AF_PP; + gpio_init.Pull = GPIO_PULLUP; + gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; + gpio_init.Alternate = USART_GPIO_AF; + HAL_GPIO_Init(USART_RX_GPIO_PORT, &gpio_init); - // Configure the LED - LED_CLK_EN(); - gpio_init.Pin = LED_PIN; - gpio_init.Mode = GPIO_MODE_OUTPUT_PP; - gpio_init.Pull = GPIO_PULLUP; - gpio_init.Speed = GPIO_SPEED_FREQ_LOW; - gpio_init.Alternate = 0; - HAL_GPIO_Init( LED_PORT, &gpio_init ); + // Configure the LED + LED_CLK_EN(); + gpio_init.Pin = LED_PIN; + gpio_init.Mode = GPIO_MODE_OUTPUT_PP; + gpio_init.Pull = GPIO_PULLUP; + gpio_init.Speed = GPIO_SPEED_FREQ_LOW; + gpio_init.Alternate = 0; + HAL_GPIO_Init(LED_PORT, &gpio_init); - // Default LED state is off - board_led_write( false ); + // Default LED state is off + board_led_write(false); - // Configure the button - BUTTON_CLK_EN(); - gpio_init.Pin = BUTTON_PIN; - gpio_init.Mode = GPIO_MODE_INPUT; - gpio_init.Pull = GPIO_PULLUP; - gpio_init.Speed = GPIO_SPEED_FREQ_LOW; - gpio_init.Alternate = 0; - HAL_GPIO_Init( BUTTON_PORT, &gpio_init ); + // Configure the button + BUTTON_CLK_EN(); + gpio_init.Pin = BUTTON_PIN; + gpio_init.Mode = GPIO_MODE_INPUT; + gpio_init.Pull = GPIO_PULLUP; + gpio_init.Speed = GPIO_SPEED_FREQ_LOW; + gpio_init.Alternate = 0; + HAL_GPIO_Init(BUTTON_PORT, &gpio_init); - // Configure USB DM and DP pins. This is optional, and maintained only for user guidance. - gpio_init.Pin = (GPIO_PIN_7 | GPIO_PIN_6); - gpio_init.Mode = GPIO_MODE_INPUT; - gpio_init.Pull = GPIO_NOPULL; - gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; - HAL_GPIO_Init( GPIOD, &gpio_init ); + // Configure USB DM and DP pins. This is optional, and maintained only for user guidance. + gpio_init.Pin = (GPIO_PIN_7 | GPIO_PIN_6); + gpio_init.Mode = GPIO_MODE_INPUT; + gpio_init.Pull = GPIO_NOPULL; + gpio_init.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOD, &gpio_init); } -static void board_uart_configuration( void ) -{ - uart_handle = ( UART_HandleTypeDef ) { - .Instance = USART_DEV, - .Init.BaudRate = CFG_BOARD_UART_BAUDRATE, +static void board_uart_configuration(void) { + uart_handle = ( UART_HandleTypeDef){ + .Instance = USART_DEV, + .Init.BaudRate = CFG_BOARD_UART_BAUDRATE, .Init.WordLength = UART_WORDLENGTH_8B, - .Init.StopBits = UART_STOPBITS_1, - .Init.Parity = UART_PARITY_NONE, - .Init.HwFlowCtl = UART_HWCONTROL_NONE, - .Init.Mode = UART_MODE_TX_RX, + .Init.StopBits = UART_STOPBITS_1, + .Init.Parity = UART_PARITY_NONE, + .Init.HwFlowCtl = UART_HWCONTROL_NONE, + .Init.Mode = UART_MODE_TX_RX, .Init.OverSampling = UART_OVERSAMPLING_16 - }; - HAL_UART_Init( &uart_handle ); + }; + HAL_UART_Init(&uart_handle); } -void board_init( void ) -{ - board_system_clock_config(); - board_gpio_configuration(); - board_uart_configuration(); +void board_init(void) { + board_system_clock_config(); + board_gpio_configuration(); + board_uart_configuration(); -#ifdef USB_OTG_HS - // STM32WBA65/64/62 only has 1 USB HS port + #ifdef USB_OTG_HS + // STM32WBA65/64/62 only has 1 USB HS port - #if CFG_TUSB_OS == OPT_OS_NONE - // 1ms tick timer - SysTick_Config( SystemCoreClock / 1000 ); - #elif CFG_TUSB_OS == OPT_OS_FREERTOS - // Explicitly disable systick to prevent its ISR runs before scheduler start - SysTick->CTRL &= ~1U; + #if CFG_TUSB_OS == OPT_OS_NONE + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); + #elif CFG_TUSB_OS == OPT_OS_FREERTOS + // Explicitly disable systick to prevent its ISR runs before scheduler start + SysTick->CTRL &= ~1U; - // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) - NVIC_SetPriority( OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ); - #endif + // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher ) + NVIC_SetPriority(USB_OTG_HS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY); + #endif - // USB clock enable - __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); - __HAL_RCC_USB_OTG_HS_PHY_CLK_ENABLE(); + // USB clock enable + __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); + __HAL_RCC_USB_OTG_HS_PHY_CLK_ENABLE(); - // See the reference manual section 11.4.7 for the USB OTG powering sequence + // See the reference manual section 11.4.7 for the USB OTG powering sequence - // Remove the VDDUSB power isolation - PWR->SVMCR |= PWR_SVMCR_USV; + // Remove the VDDUSB power isolation + PWR->SVMCR |= PWR_SVMCR_USV; - // Enable VDD11USB supply by clearing VDD11USBDIS to 0 - PWR->VOSR &= ~PWR_VOSR_VDD11USBDIS; + // Enable VDD11USB supply by clearing VDD11USBDIS to 0 + PWR->VOSR &= ~PWR_VOSR_VDD11USBDIS; - // Enable USB OTG internal power by setting USBPWREN to 1 - PWR->VOSR |= PWR_VOSR_USBPWREN; + // Enable USB OTG internal power by setting USBPWREN to 1 + PWR->VOSR |= PWR_VOSR_USBPWREN; - // Wait for VDD11USB supply to be ready in VDD11USBRDY = 1 - while ((PWR->VOSR & PWR_VOSR_VDD11USBRDY) == 0) {} + // Wait for VDD11USB supply to be ready in VDD11USBRDY = 1 + while ((PWR->VOSR & PWR_VOSR_VDD11USBRDY) == 0) {} - // Enable USB OTG booster by setting USBBOOSTEN to 1 - PWR->VOSR |= PWR_VOSR_USBBOOSTEN; + // Enable USB OTG booster by setting USBBOOSTEN to 1 + PWR->VOSR |= PWR_VOSR_USBBOOSTEN; - // Wait for USB OTG booster to be ready in USBBOOSTRDY = 1 - while ((PWR->VOSR & PWR_VOSR_USBBOOSTRDY) == 0) {} + // Wait for USB OTG booster to be ready in USBBOOSTRDY = 1 + while ((PWR->VOSR & PWR_VOSR_USBBOOSTRDY) == 0) {} - // Enable USB power on Pwrctrl CR2 register - PWR->SVMCR |= PWR_SVMCR_USV; + // Enable USB power on Pwrctrl CR2 register + PWR->SVMCR |= PWR_SVMCR_USV; - // Set the reference clock selection (must match the clock source) - SYSCFG->OTGHSPHYCR &= ~SYSCFG_OTGHSPHYCR_CLKSEL; - SYSCFG->OTGHSPHYCR |= SYSCFG_OTGHSPHYCR_CLKSEL_0 | SYSCFG_OTGHSPHYCR_CLKSEL_1 | - SYSCFG_OTGHSPHYCR_CLKSEL_3; // 32MHz clock + // Set the reference clock selection (must match the clock source) + SYSCFG->OTGHSPHYCR &= ~SYSCFG_OTGHSPHYCR_CLKSEL; + SYSCFG->OTGHSPHYCR |= SYSCFG_OTGHSPHYCR_CLKSEL_0 | SYSCFG_OTGHSPHYCR_CLKSEL_1 | + SYSCFG_OTGHSPHYCR_CLKSEL_3;// 32MHz clock - // Configuring the SYSCFG registers OTG_HS PHY - SYSCFG->OTGHSPHYCR |= SYSCFG_OTGHSPHYCR_EN; + // Configuring the SYSCFG registers OTG_HS PHY + SYSCFG->OTGHSPHYCR |= SYSCFG_OTGHSPHYCR_EN; - // Disable VBUS sense (B device) - USB_OTG_HS->GCCFG &= ~USB_OTG_GCCFG_VBDEN; + // Disable VBUS sense (B device) + USB_OTG_HS->GCCFG &= ~USB_OTG_GCCFG_VBDEN; - // B-peripheral session valid override enable - USB_OTG_HS->GCCFG |= USB_OTG_GCCFG_VBVALEXTOEN; - USB_OTG_HS->GCCFG |= USB_OTG_GCCFG_VBVALOVAL; -#endif // USB_OTG_FS + // B-peripheral session valid override enable + USB_OTG_HS->GCCFG |= USB_OTG_GCCFG_VBVALEXTOEN; + USB_OTG_HS->GCCFG |= USB_OTG_GCCFG_VBVALOVAL; + #endif // USB_OTG_FS } -void board_led_write( bool state ) -{ - HAL_GPIO_WritePin( LED_PORT, LED_PIN, state ? LED_STATE_ON : ( 1 - LED_STATE_ON ) ); +void board_led_write(bool state) { HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON)); } + +uint32_t board_button_read(void) { return HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN) == BUTTON_STATE_ACTIVE; } + +int board_uart_read(uint8_t *buf, int len) { + (void) buf; + (void) len; + return 0; } -uint32_t board_button_read( void ) -{ - return HAL_GPIO_ReadPin( BUTTON_PORT, BUTTON_PIN ) == BUTTON_STATE_ACTIVE; -} - -int board_uart_read( uint8_t *buf, int len ) -{ - ( void ) buf; - ( void ) len; - return 0; -} - -int board_uart_write( void const *buf, int len ) -{ - ( void ) HAL_UART_Transmit( &uart_handle, ( const uint8_t * ) buf, len, USART_TIMEOUT_TICKS ); - return len; +int board_uart_write(void const *buf, int len) { + (void) HAL_UART_Transmit(&uart_handle, (const uint8_t *) buf, len, USART_TIMEOUT_TICKS); + return len; } #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -void SysTick_Handler( void ) -{ - HAL_IncTick(); - system_ticks++; + +void SysTick_Handler(void) { + HAL_IncTick(); + system_ticks++; } -uint32_t board_millis( void ) -{ - return system_ticks; -} +uint32_t board_millis(void) { return system_ticks; } #endif -void HardFault_Handler( void ) -{ - asm( "bkpt 1" ); -} +void HardFault_Handler(void) { asm( "bkpt 1" ); } // Required by __libc_init_array in startup code if we are compiling using -nostdlib/-nostartfiles. -void _init( void ); -void _init( void ) -{ } +void _init(void); + +void _init(void) {} diff --git a/hw/bsp/stm32wba/family.cmake b/hw/bsp/stm32wba/family.cmake index 3f41900ea..3f42879be 100644 --- a/hw/bsp/stm32wba/family.cmake +++ b/hw/bsp/stm32wba/family.cmake @@ -4,7 +4,7 @@ set(ST_FAMILY wba) set(ST_PREFIX stm32${ST_FAMILY}xx) set(ST_HAL_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver) -set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis_device_${ST_FAMILY}) +set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis-device-${ST_FAMILY}) set(CMSIS_5 ${TOP}/lib/CMSIS_5) # include board specific @@ -19,25 +19,12 @@ set(FAMILY_MCUS STM32WBA CACHE INTERNAL "") # ---------------------- # Port & Speed Selection # ---------------------- -if (NOT DEFINED RHPORT_DEVICE) - set(RHPORT_DEVICE 0) -endif () -if (NOT DEFINED RHPORT_HOST) - set(RHPORT_HOST 0) -endif () +set(RHPORT_DEVICE 0) +set(RHPORT_HOST 0) -if (NOT DEFINED RHPORT_SPEED) - # WBA65/64/62 has built-in HS PHY - set(RHPORT_SPEED OPT_MODE_HIGH_SPEED OPT_MODE_HIGH_SPEED) -endif () -if (NOT DEFINED RHPORT_DEVICE_SPEED) - list(GET RHPORT_SPEED ${RHPORT_DEVICE} RHPORT_DEVICE_SPEED) -endif () -if (NOT DEFINED RHPORT_HOST_SPEED) - list(GET RHPORT_SPEED ${RHPORT_HOST} RHPORT_HOST_SPEED) -endif () - -cmake_print_variables(RHPORT_DEVICE RHPORT_DEVICE_SPEED RHPORT_HOST RHPORT_HOST_SPEED) +# WBA65/64/62 has built-in HS PHY +set(RHPORT_DEVICE_SPEED OPT_MODE_HIGH_SPEED) +set(RHPORT_HOST_SPEED OPT_MODE_HIGH_SPEED) #------------------------------------ # BOARD_TARGET @@ -57,7 +44,7 @@ function(add_board_target BOARD_TARGET) set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU}) set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s) - set(LD_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/linker/${UPPERCASE_MCU_VARIANT}_FLASH_ns.ld) + set(LD_FILE_GNU ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/linker/${UPPERCASE_MCU_VARIANT}_FLASH_ns.ld) set(LD_FILE_Clang ${LD_FILE_GNU}) set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash_ns.icf) @@ -66,15 +53,15 @@ function(add_board_target BOARD_TARGET) ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_cortex.c ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_icache.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pcd.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pcd_ex.c - ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_ll_usb.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pwr_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_rcc_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_gpio.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pcd.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_pcd_ex.c + ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_ll_usb.c ${STARTUP_FILE_${CMAKE_C_COMPILER_ID}} ) target_include_directories(${BOARD_TARGET} PUBLIC diff --git a/hw/bsp/stm32wba/family.mk b/hw/bsp/stm32wba/family.mk index 22f63609f..9b319921f 100644 --- a/hw/bsp/stm32wba/family.mk +++ b/hw/bsp/stm32wba/family.mk @@ -13,10 +13,11 @@ CFLAGS += \ CFLAGS_GCC += \ -flto \ - -nostdlib -nostartfiles \ -Wno-error=cast-align -Wno-unused-parameter -LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs -Wl,--gc-sections +LDFLAGS_GCC += \ + -nostdlib -nostartfiles \ + -specs=nosys.specs -specs=nano.specs -Wl,--gc-sections SRC_C += \ src/portable/synopsys/dwc2/dcd_dwc2.c \ @@ -44,14 +45,14 @@ INC += \ $(TOP)/$(ST_HAL_DRIVER)/Inc # STM32WBA HAL uses uppercase MCU_VARIANT (excluding the x's) for linking and lowercase MCU_VARIANT for startup. -UPPERCASE_MCU_VARIANT = $(shell echo $(MCU_VARIANT) | sed 's/\([^x]\)/\U\1/g') +UPPERCASE_MCU_VARIANT = $(subst XX,xx,$(call to_upper,$(MCU_VARIANT))) # Startup - Manually specify lowercase version for startup file SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_$(MCU_VARIANT).s SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_$(MCU_VARIANT).s # Linker -LD_FILE_GCC ?= ${ST_CMSIS}/Source/Templates/gcc/linker/${UPPERCASE_MCU_VARIANT}_FLASH_ns.ld +LD_FILE_GCC ?= ${FAMILY_PATH}/linker/${UPPERCASE_MCU_VARIANT}_FLASH_ns.ld LD_FILE_IAR ?= $(ST_CMSIS)/Source/Templates/iar/linker/$(MCU_VARIANT)_flash_ns.icf # flash target using on-board stlink diff --git a/hw/bsp/stm32wba/linker/STM32WBA65xx_FLASH_ns.ld b/hw/bsp/stm32wba/linker/STM32WBA65xx_FLASH_ns.ld new file mode 100644 index 000000000..bc1f2997d --- /dev/null +++ b/hw/bsp/stm32wba/linker/STM32WBA65xx_FLASH_ns.ld @@ -0,0 +1,188 @@ +/* +****************************************************************************** +** +** File : LinkerScript.ld +** +** Author : STM32CubeIDE +** +** Abstract : Linker script for STM32WBA65xx Device from STM32WBA series +** 2048Kbytes FLASH +** 512Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +****************************************************************************** +** @attention +** +** Copyright (c) 2024 STMicroelectronics. +** All rights reserved. +** +** This software is licensed under terms that can be found in the LICENSE file +** in the root directory of this software component. +** If no LICENSE file comes with this software, it is provided AS-IS. +** +****************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +_Min_Heap_Size = 0x200; /* required amount of heap */ +_Min_Stack_Size = 0x400; /* required amount of stack */ + +/* Memories definition */ +MEMORY +{ + RAM (xrw) : ORIGIN = 0x20038000, LENGTH = 224K + RAM2 (xrw) : ORIGIN = 0x20078000, LENGTH = 32K + FLASH (rx) : ORIGIN = 0x08100000, LENGTH = 1024K +} + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ + +/* Sections */ +SECTIONS +{ + /* The startup code into "FLASH" Rom type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data into "FLASH" Rom type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data into "FLASH" Rom type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : + { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + + .ARM : + { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + + .init_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + + .fini_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> FLASH + + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} From ba36df6233cd1bd09f383818f10c1ccda7b9efb4 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 12 Sep 2025 11:27:31 +0700 Subject: [PATCH 370/382] fix warnings, update docs --- docs/reference/boards.rst | 33 ++++++++++--------- .../audio_4_channel_mic_freertos/src/main.c | 2 -- .../device/audio_test_freertos/src/main.c | 2 -- examples/device/cdc_msc_freertos/src/main.c | 4 +-- .../device/cdc_msc_freertos/src/msc_disk.c | 2 +- examples/device/midi_test_freertos/src/main.c | 2 -- .../uac2_speaker_fb/src/quirk_os_guessing.c | 8 ++--- examples/device/usbtmc/src/usbtmc_app.c | 4 +-- .../at32f402_405/boards/at_start_f402/board.h | 4 +-- .../boards/at32f403a_weact_blackpill/board.h | 2 +- .../boards/at_start_f407/board.h | 4 +-- .../at32f435_437/boards/at_start_f435/board.h | 4 +-- hw/bsp/stm32n6/boards/stm32n6570dk/board.h | 2 +- 13 files changed, 33 insertions(+), 40 deletions(-) diff --git a/docs/reference/boards.rst b/docs/reference/boards.rst index a930f485b..25542264c 100644 --- a/docs/reference/boards.rst +++ b/docs/reference/boards.rst @@ -28,22 +28,23 @@ max78002evkit MAX78002 EVKIT maxim https://www.analog.com/en/resources/e ============= ================ ======== ================================================================================================================= ====== Artery ------ +------ -============== ============== ============= ================================================== ====== -Board Name Family URL Note -============== ============== ============= ================================================== ====== -at_start_f402 AT-START-F402 at32f402_405 https://www.arterychip.com/en/product/AT32F402.jsp -at_start_f405 AT-START-F405 at32f402_405 https://www.arterychip.com/en/product/AT32F405.jsp -at_start_f403a AT-START-F403a at32f403a_407 https://www.arterychip.com/en/product/AT32F403A.jsp -at_start_f407 AT-START-F407 at32f403a_407 https://www.arterychip.com/en/product/AT32F407.jsp -at_start_f413 AT-START-F413 at32f413 https://www.arterychip.com/en/product/AT32F413.jsp -at_start_f415 AT-START-F415 at32f415 https://www.arterychip.com/en/product/AT32F415.jsp -at_start_f423 AT-START-F423 at32f423 https://www.arterychip.com/en/product/AT32F423.jsp -at_start_f425 AT-START-F425 at32f425 https://www.arterychip.com/en/product/AT32F425.jsp -at_start_f435 AT-START-F435 at32f435_437 https://www.arterychip.com/en/product/AT32F435.jsp -at_start_f437 AT-START-F437 at32f435_437 https://www.arterychip.com/en/product/AT32F437.jsp -============== ============== ============= ================================================== ====== +========================= ============================= ============= ==================================================== ====== +Board Name Family URL Note +========================= ============================= ============= ==================================================== ====== +at_start_f402 AT-START-F402 at32f402_405 https://www.arterychip.com/en/product/AT32F402.jsp +at_start_f405 AT-START-F405 at32f402_405 https://www.arterychip.com/en/product/AT32F405.jsp +at32f403a_weact_blackpill WeAct BlackPill AT32F403ACGU7 at32f403a_407 https://github.com/WeActStudio/WeActStudio.BlackPill +at_start_f403a AT-START-F403a at32f403a_407 https://www.arterychip.com/en/product/AT32F403.jsp +at_start_f407 AT-START-F407 at32f403a_407 https://www.arterychip.com/en/product/AT32F407.jsp +at_start_f413 AT-START-F413 at32f413 https://www.arterychip.com/en/product/AT32F413.jsp +at_start_f415 AT-START-F415 at32f415 https://www.arterychip.com/en/product/AT32F415.jsp +at_start_f423 AT-START-F423 at32f423 https://www.arterychip.com/en/product/AT32F423.jsp +at_start_f425 AT-START-F425 at32f425 https://www.arterychip.com/en/product/AT32F425.jsp +at_start_f435 AT-START-F435 at32f435_437 https://www.arterychip.com/en/product/AT32F435.jsp +at_start_f437 AT-START-F437 at32f435_437 https://www.arterychip.com/en/product/AT32F437.jsp +========================= ============================= ============= ==================================================== ====== Bridgetek --------- @@ -303,7 +304,7 @@ stm32u575eval STM32 U575 Eval stm32u5 https://www.s stm32u575nucleo STM32 U575 Nucleo stm32u5 https://www.st.com/en/evaluation-tools/nucleo-u575zi-q.html stm32u5a5nucleo STM32 U5a5 Nucleo stm32u5 https://www.st.com/en/evaluation-tools/nucleo-u5a5zj-q.html stm32wb55nucleo STM32 P-NUCLEO-WB55 stm32wb https://www.st.com/en/evaluation-tools/p-nucleo-wb55.html -stm32wba65nucleo STM32 NUCLEO-WBA65RI stm32wba https://www.st.com/en/evaluation-tools/nucleo-wba65ri.html +stm32wba_nucleo STM32 NUCLEO-WBA65RI stm32wba https://www.st.com/en/evaluation-tools/nucleo-wba65ri.html =================== ================================= ========= ================================================================= ====== Sunxi diff --git a/examples/device/audio_4_channel_mic_freertos/src/main.c b/examples/device/audio_4_channel_mic_freertos/src/main.c index 9c76380a2..643b2f259 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/main.c +++ b/examples/device/audio_4_channel_mic_freertos/src/main.c @@ -476,13 +476,11 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p //--------------------------------------------------------------------+ void led_blinking_task(void *param) { (void) param; - static uint32_t start_ms = 0; static bool led_state = false; while (1) { // Blink every interval ms vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); - start_ms += blink_interval_ms; board_led_write(led_state); led_state = 1 - led_state;// toggle diff --git a/examples/device/audio_test_freertos/src/main.c b/examples/device/audio_test_freertos/src/main.c index b2bed295f..ea06af0e2 100644 --- a/examples/device/audio_test_freertos/src/main.c +++ b/examples/device/audio_test_freertos/src/main.c @@ -470,13 +470,11 @@ bool tud_audio_set_itf_close_ep_cb(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ void led_blinking_task(void *param) { (void) param; - static uint32_t start_ms = 0; static bool led_state = false; while (1) { // Blink every interval ms vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); - start_ms += blink_interval_ms; board_led_write(led_state); led_state = 1 - led_state;// toggle diff --git a/examples/device/cdc_msc_freertos/src/main.c b/examples/device/cdc_msc_freertos/src/main.c index 09ccc9bf3..b20d162ab 100644 --- a/examples/device/cdc_msc_freertos/src/main.c +++ b/examples/device/cdc_msc_freertos/src/main.c @@ -229,13 +229,11 @@ void tud_cdc_rx_cb(uint8_t itf) { //--------------------------------------------------------------------+ void led_blinking_task(void* param) { (void) param; - static uint32_t start_ms = 0; - static bool led_state = false; + static bool led_state = false; while (1) { // Blink every interval ms vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); - start_ms += blink_interval_ms; board_led_write(led_state); led_state = 1 - led_state; // toggle diff --git a/examples/device/cdc_msc_freertos/src/msc_disk.c b/examples/device/cdc_msc_freertos/src/msc_disk.c index 3602c991d..849712e6a 100644 --- a/examples/device/cdc_msc_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_freertos/src/msc_disk.c @@ -150,7 +150,7 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = }; #if CFG_EXAMPLE_MSC_ASYNC_IO -void msc_disk_init() { +void msc_disk_init(void) { #if configSUPPORT_STATIC_ALLOCATION io_queue = xQueueCreateStatic(1, sizeof(io_ops_t), io_queue_buf, &io_queue_static); diff --git a/examples/device/midi_test_freertos/src/main.c b/examples/device/midi_test_freertos/src/main.c index 3e406d38d..c18ad6ada 100644 --- a/examples/device/midi_test_freertos/src/main.c +++ b/examples/device/midi_test_freertos/src/main.c @@ -225,13 +225,11 @@ void midi_task(void* param) { //--------------------------------------------------------------------+ void led_blinking_task(void* param) { (void) param; - static uint32_t start_ms = 0; static bool led_state = false; while (1) { // Blink every interval ms vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); - start_ms += blink_interval_ms; board_led_write(led_state); led_state = 1 - led_state; // toggle diff --git a/examples/device/uac2_speaker_fb/src/quirk_os_guessing.c b/examples/device/uac2_speaker_fb/src/quirk_os_guessing.c index 965bbd6cf..92b9ab6ee 100644 --- a/examples/device/uac2_speaker_fb/src/quirk_os_guessing.c +++ b/examples/device/uac2_speaker_fb/src/quirk_os_guessing.c @@ -29,12 +29,12 @@ static tusb_desc_type_t desc_req_buf[2]; static int desc_req_idx = 0; // Place at the start of tud_descriptor_device_cb() -void quirk_os_guessing_desc_device_cb() { +void quirk_os_guessing_desc_device_cb(void) { desc_req_idx = 0; } // Place at the start of tud_descriptor_configuration_cb() -void quirk_os_guessing_desc_configuration_cb() { +void quirk_os_guessing_desc_configuration_cb(void) { // Skip redundant request if (desc_req_idx == 0 || (desc_req_idx == 1 && desc_req_buf[0] != TUSB_DESC_CONFIGURATION)) { desc_req_buf[desc_req_idx++] = TUSB_DESC_CONFIGURATION; @@ -42,7 +42,7 @@ void quirk_os_guessing_desc_configuration_cb() { } // Place at the start of tud_descriptor_bos_cb() -void quirk_os_guessing_desc_bos_cb() { +void quirk_os_guessing_desc_bos_cb(void) { // Skip redundant request if (desc_req_idx == 0 || (desc_req_idx == 1 && desc_req_buf[0] != TUSB_DESC_BOS)) { desc_req_buf[desc_req_idx++] = TUSB_DESC_BOS; @@ -50,7 +50,7 @@ void quirk_os_guessing_desc_bos_cb() { } // Place at the start of tud_descriptor_string_cb() -void quirk_os_guessing_desc_string_cb() { +void quirk_os_guessing_desc_string_cb(void) { // Skip redundant request if (desc_req_idx == 0 || (desc_req_idx == 1 && desc_req_buf[0] != TUSB_DESC_STRING)) { desc_req_buf[desc_req_idx++] = TUSB_DESC_STRING; diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index fb25982c7..e738f1008 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -99,7 +99,7 @@ usbtmc_response_capabilities_488_t const * #else usbtmc_response_capabilities_t const * #endif -tud_usbtmc_get_capabilities_cb() +tud_usbtmc_get_capabilities_cb(void) { return &tud_usbtmc_app_capabilities; } @@ -161,7 +161,7 @@ bool tud_usbtmc_msg_data_cb(void *data, size_t len, bool transfer_complete) return true; } -bool tud_usbtmc_msgBulkIn_complete_cb() +bool tud_usbtmc_msgBulkIn_complete_cb(void) { if((buffer_tx_ix == buffer_len) || idnQuery) // done { diff --git a/hw/bsp/at32f402_405/boards/at_start_f402/board.h b/hw/bsp/at32f402_405/boards/at_start_f402/board.h index b11b7a80f..01b78f101 100644 --- a/hw/bsp/at32f402_405/boards/at_start_f402/board.h +++ b/hw/bsp/at32f402_405/boards/at_start_f402/board.h @@ -25,8 +25,8 @@ */ /* metadata: - name: AT-START-F405 - url: https://www.arterychip.com/en/product/AT32F405.jsp + name: AT-START-F402 + url: https://www.arterychip.com/en/product/AT32F402.jsp */ #ifndef BOARD_H_ diff --git a/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h b/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h index 005c5aed6..2dac9bc56 100644 --- a/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h +++ b/hw/bsp/at32f403a_407/boards/at32f403a_weact_blackpill/board.h @@ -25,7 +25,7 @@ */ /* metadata: - name: WeAct Studio BlackPill AT32F403ACGU7 + name: WeAct BlackPill AT32F403ACGU7 url: https://github.com/WeActStudio/WeActStudio.BlackPill */ diff --git a/hw/bsp/at32f403a_407/boards/at_start_f407/board.h b/hw/bsp/at32f403a_407/boards/at_start_f407/board.h index 753fece10..c490d7ed6 100644 --- a/hw/bsp/at32f403a_407/boards/at_start_f407/board.h +++ b/hw/bsp/at32f403a_407/boards/at_start_f407/board.h @@ -25,8 +25,8 @@ */ /* metadata: - name: AT-START-F403a - url: https://www.arterychip.com/en/product/AT32F403.jsp + name: AT-START-F407 + url: https://www.arterychip.com/en/product/AT32F407.jsp */ #ifndef BOARD_H_ diff --git a/hw/bsp/at32f435_437/boards/at_start_f435/board.h b/hw/bsp/at32f435_437/boards/at_start_f435/board.h index 3522e759a..25fd81450 100644 --- a/hw/bsp/at32f435_437/boards/at_start_f435/board.h +++ b/hw/bsp/at32f435_437/boards/at_start_f435/board.h @@ -25,8 +25,8 @@ */ /* metadata: - name: AT-START-F437 - url: https://www.arterychip.com/en/product/AT32F437.jsp + name: AT-START-F435 + url: https://www.arterychip.com/en/product/AT32F435.jsp */ #ifndef BOARD_H_ diff --git a/hw/bsp/stm32n6/boards/stm32n6570dk/board.h b/hw/bsp/stm32n6/boards/stm32n6570dk/board.h index 96e430c7a..a3d945f76 100644 --- a/hw/bsp/stm32n6/boards/stm32n6570dk/board.h +++ b/hw/bsp/stm32n6/boards/stm32n6570dk/board.h @@ -25,7 +25,7 @@ */ /* metadata: - name: STM32N6570-DK + name: STM32 N6570-DK url: https://www.st.com/en/evaluation-tools/stm32n6570-dk.html */ From 9f055f113c38b6fbd898231bc1636448712adf14 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 12 Sep 2025 11:34:06 +0700 Subject: [PATCH 371/382] missing cmsis5 for wba --- tools/get_deps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/get_deps.py b/tools/get_deps.py index 282331f82..0828140c1 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -240,7 +240,7 @@ deps_optional = { 'imxrt kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx mm32 msp432e4 nrf saml2x ' 'lpc11 lpc13 lpc15 lpc17 lpc18 lpc40 lpc43 ' 'stm32c0 stm32f0 stm32f1 stm32f2 stm32f3 stm32f4 stm32f7 stm32g0 stm32g4 stm32h5 ' - 'stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32n6 stm32u5 stm32wb ' + 'stm32h7 stm32h7rs stm32l0 stm32l1 stm32l4 stm32l5 stm32n6 stm32u5 stm32wb stm32wba' 'sam3x samd11 samd21 samd51 samd5x_e5x same5x same7x saml2x samg ' 'tm4c '], 'lib/CMSIS_6': ['https://github.com/ARM-software/CMSIS_6.git', From d3ab48bd79e53adbe763c924508edda1d60a968d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Sep 2025 11:09:43 +0200 Subject: [PATCH 372/382] Fix IAR build Signed-off-by: HiFiPhile --- hw/bsp/imxrt/family.cmake | 2 -- hw/bsp/imxrt/family.mk | 2 -- 2 files changed, 4 deletions(-) diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake index 6224b63a4..feec4973f 100644 --- a/hw/bsp/imxrt/family.cmake +++ b/hw/bsp/imxrt/family.cmake @@ -68,8 +68,6 @@ function(add_board_target BOARD_TARGET) if (NOT M4 STREQUAL "1") target_compile_definitions(${BOARD_TARGET} PUBLIC - __ARMVFP__=0 - __ARMFPV5__=0 XIP_EXTERNAL_FLASH=1 XIP_BOOT_HEADER_ENABLE=1 ) diff --git a/hw/bsp/imxrt/family.mk b/hw/bsp/imxrt/family.mk index 9a2c37121..353f64e57 100644 --- a/hw/bsp/imxrt/family.mk +++ b/hw/bsp/imxrt/family.mk @@ -14,8 +14,6 @@ CFLAGS += \ ifneq ($(M4), 1) CFLAGS += \ - -D__ARMVFP__=0 \ - -D__ARMFPV5__=0 \ -DXIP_EXTERNAL_FLASH=1 \ -DXIP_BOOT_HEADER_ENABLE=1 endif From 5755afa690f242988c02932068339ad5ffc4404e Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Sep 2025 11:39:41 +0200 Subject: [PATCH 373/382] Fix some IAR warnings Signed-off-by: HiFiPhile --- src/class/hid/hid_host.c | 3 ++- src/host/usbh.c | 27 ++++++++++++++------------- src/portable/ehci/ehci.c | 5 +++-- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index 56fccdd22..a44c83433 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -519,7 +519,8 @@ bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const* desc_ // Assume bNumDescriptors = 1 p_hid->report_desc_type = desc_hid->bReportType; - p_hid->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength); + // Use offsetof to avoid pointer to the odd/misaligned address + p_hid->report_desc_len = tu_unaligned_read16((uint8_t const*)desc_hid + offsetof(tusb_hid_descriptor_hid_t, wReportLength)); // Per HID Specs: default is Report protocol, though we will force Boot protocol when set_config p_hid->protocol_mode = _hidh_default_protocol; diff --git a/src/host/usbh.c b/src/host/usbh.c index ce83977c5..1c63ac712 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -400,7 +400,7 @@ bool tuh_descriptor_get_device_local(uint8_t daddr, tusb_desc_device_t* desc_dev tusb_speed_t tuh_speed_get(uint8_t daddr) { tuh_bus_info_t bus_info; tuh_bus_info_get(daddr, &bus_info); - return bus_info.speed; + return (tusb_speed_t)bus_info.speed; } bool tuh_rhport_is_active(uint8_t rhport) { @@ -651,7 +651,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { tuh_xfer_t xfer = { .daddr = event.dev_addr, .ep_addr = ep_addr, - .result = event.xfer_complete.result, + .result = (xfer_result_t)event.xfer_complete.result, .actual_len = event.xfer_complete.len, .buflen = 0, // not available .buffer = NULL, // not available @@ -832,18 +832,19 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t } TU_ATTR_FALLTHROUGH; - case CONTROL_STAGE_DATA: - if (request->wLength) { - TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, daddr); - TU_LOG_MEM_USBH(ctrl_info->buffer, xferred_bytes, 2); - } - ctrl_info->actual_len = (uint16_t) xferred_bytes; + case CONTROL_STAGE_DATA: { + if (request->wLength) { + TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, daddr); + TU_LOG_MEM_USBH(ctrl_info->buffer, xferred_bytes, 2); + } + ctrl_info->actual_len = (uint16_t) xferred_bytes; - // ACK stage: toggle is always 1 - _control_set_xfer_stage(CONTROL_STAGE_ACK); - const uint8_t ep_status = tu_edpt_addr(0, 1 - request->bmRequestType_bit.direction); - TU_ASSERT(hcd_edpt_xfer(rhport, daddr, ep_status, NULL, 0)); - break; + // ACK stage: toggle is always 1 + _control_set_xfer_stage(CONTROL_STAGE_ACK); + const uint8_t ep_status = tu_edpt_addr(0, 1 - request->bmRequestType_bit.direction); + TU_ASSERT(hcd_edpt_xfer(rhport, daddr, ep_status, NULL, 0)); + break; + } case CONTROL_STAGE_ACK: { // Abort all pending transfers if SET_CONFIGURATION request diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index da9f49d29..b372fe635 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -184,7 +184,8 @@ static void ehci_enable_schedule(ehci_registers_t* regs, bool is_period) { //--------------------------------------------------------------------+ uint32_t hcd_frame_number(uint8_t rhport) { (void) rhport; - return (ehci_data.uframe_number + ehci_data.regs->frame_index) >> 3; + uint32_t uframe = ehci_data.regs->frame_index; + return (ehci_data.uframe_number + uframe) >> 3; } void hcd_port_reset(uint8_t rhport) { @@ -896,7 +897,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c p_qhd->used = 1; p_qhd->removing = 0; p_qhd->attached_qtd = NULL; - p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint + p_qhd->pid = tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint //------------- active, but no TD list -------------// p_qhd->qtd_overlay.halted = 0; From 3b4884f8d771e93ae8fe0cd0c7f0d81cd73a83b2 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Sep 2025 14:06:57 +0200 Subject: [PATCH 374/382] Move BOARD_ConfigMPU into board specific init Signed-off-by: HiFiPhile --- hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h | 389 +++++++++++++++++++ hw/bsp/imxrt/family.c | 392 +------------------- 2 files changed, 394 insertions(+), 387 deletions(-) diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h index c5d54b7a7..05bd2069f 100644 --- a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h +++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h @@ -49,4 +49,393 @@ #define UART_PORT LPUART1 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_LPUART10_CLK_ROOT +// Additional board init for MPU configuration +#define BOARD_INIT_2 1 + +//-------------------------------------------------------------------- +// MPU configuration +//-------------------------------------------------------------------- +#if __CORTEX_M == 7 +static void BOARD_ConfigMPU(void) { + #if defined(__CC_ARM) || defined(__ARMCC_VERSION) + extern uint32_t Image$$RW_m_ncache$$Base[]; + /* RW_m_ncache_unused is a auxiliary region which is used to get the whole size of noncache section */ + extern uint32_t Image$$RW_m_ncache_unused$$Base[]; + extern uint32_t Image$$RW_m_ncache_unused$$ZI$$Limit[]; + uint32_t nonCacheStart = (uint32_t) Image$$RW_m_ncache$$Base; + uint32_t size = ((uint32_t) Image$$RW_m_ncache_unused$$Base == nonCacheStart) ? 0 : ((uint32_t) Image$$RW_m_ncache_unused$$ZI$$Limit - nonCacheStart); + #elif defined(__MCUXPRESSO) + #if defined(__USE_SHMEM) + extern uint32_t __base_rpmsg_sh_mem; + extern uint32_t __top_rpmsg_sh_mem; + uint32_t nonCacheStart = (uint32_t) (&__base_rpmsg_sh_mem); + uint32_t size = (uint32_t) (&__top_rpmsg_sh_mem) - nonCacheStart; + #else + extern uint32_t __base_NCACHE_REGION; + extern uint32_t __top_NCACHE_REGION; + uint32_t nonCacheStart = (uint32_t) (&__base_NCACHE_REGION); + uint32_t size = (uint32_t) (&__top_NCACHE_REGION) - nonCacheStart; + #endif + #elif defined(__ICCARM__) || defined(__GNUC__) + extern uint32_t __NCACHE_REGION_START[]; + extern uint32_t __NCACHE_REGION_SIZE[]; + uint32_t nonCacheStart = (uint32_t) __NCACHE_REGION_START; + uint32_t size = (uint32_t) __NCACHE_REGION_SIZE; + #endif + volatile uint32_t i = 0; + + #if defined(__ICACHE_PRESENT) && __ICACHE_PRESENT + /* Disable I cache and D cache */ + if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR)) { + SCB_DisableICache(); + } + #endif + #if defined(__DCACHE_PRESENT) && __DCACHE_PRESENT + if (SCB_CCR_DC_Msk == (SCB_CCR_DC_Msk & SCB->CCR)) { + SCB_DisableDCache(); + } + #endif + + /* Disable MPU */ + ARM_MPU_Disable(); + + /* MPU configure: + * Use ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, + * SubRegionDisable, Size) + * API in mpu_armv7.h. + * param DisableExec Instruction access (XN) disable bit,0=instruction fetches enabled, 1=instruction fetches + * disabled. + * param AccessPermission Data access permissions, allows you to configure read/write access for User and + * Privileged mode. + * Use MACROS defined in mpu_armv7.h: + * ARM_MPU_AP_NONE/ARM_MPU_AP_PRIV/ARM_MPU_AP_URO/ARM_MPU_AP_FULL/ARM_MPU_AP_PRO/ARM_MPU_AP_RO + * Combine TypeExtField/IsShareable/IsCacheable/IsBufferable to configure MPU memory access attributes. + * TypeExtField IsShareable IsCacheable IsBufferable Memory Attribute Shareability Cache + * 0 x 0 0 Strongly Ordered shareable + * 0 x 0 1 Device shareable + * 0 0 1 0 Normal not shareable Outer and inner write + * through no write allocate + * 0 0 1 1 Normal not shareable Outer and inner write + * back no write allocate + * 0 1 1 0 Normal shareable Outer and inner write + * through no write allocate + * 0 1 1 1 Normal shareable Outer and inner write + * back no write allocate + * 1 0 0 0 Normal not shareable outer and inner + * noncache + * 1 1 0 0 Normal shareable outer and inner + * noncache + * 1 0 1 1 Normal not shareable outer and inner write + * back write/read acllocate + * 1 1 1 1 Normal shareable outer and inner write + * back write/read acllocate + * 2 x 0 0 Device not shareable + * Above are normal use settings, if your want to see more details or want to config different inner/outer cache + * policy. + * please refer to Table 4-55 /4-56 in arm cortex-M7 generic user guide + * param SubRegionDisable Sub-region disable field. 0=sub-region is enabled, 1=sub-region is disabled. + * param Size Region size of the region to be configured. use ARM_MPU_REGION_SIZE_xxx MACRO in + * mpu_armv7.h. + */ + + /* + * Add default region to deny access to whole address space to workaround speculative prefetch. + * Refer to Arm errata 1013783-B for more details. + * + */ + /* Region 0 setting: Instruction access disabled, No data access permission. */ + MPU->RBAR = ARM_MPU_RBAR(0, 0x00000000U); + MPU->RASR = ARM_MPU_RASR(1, ARM_MPU_AP_NONE, 0, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_4GB); + + /* Region 1 setting: Memory with Device type, not shareable, non-cacheable. */ + MPU->RBAR = ARM_MPU_RBAR(1, 0x80000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB); + + /* Region 2 setting: Memory with Device type, not shareable, non-cacheable. */ + MPU->RBAR = ARM_MPU_RBAR(2, 0x60000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB); + + /* Region 3 setting: Memory with Device type, not shareable, non-cacheable. */ + MPU->RBAR = ARM_MPU_RBAR(3, 0x00000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB); + + /* Region 4 setting: Memory with Normal type, not shareable, outer/inner write back */ + MPU->RBAR = ARM_MPU_RBAR(4, 0x00000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB); + + /* Region 5 setting: Memory with Normal type, not shareable, outer/inner write back */ + MPU->RBAR = ARM_MPU_RBAR(5, 0x20000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB); + + #if defined(CACHE_MODE_WRITE_THROUGH) && CACHE_MODE_WRITE_THROUGH + /* Region 6 setting: Memory with Normal type, not shareable, write through */ + MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_1MB); + + /* Region 7 setting: Memory with Normal type, not shareable, write through */ + MPU->RBAR = ARM_MPU_RBAR(7, 0x20300000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_512KB); + #else + /* Region 6 setting: Memory with Normal type, not shareable, outer/inner write back */ + MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_1MB); + + /* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */ + MPU->RBAR = ARM_MPU_RBAR(7, 0x20300000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_512KB); + #endif + + #if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1) + /* Region 8 setting: Memory with Normal type, not shareable, outer/inner write back. */ + MPU->RBAR = ARM_MPU_RBAR(8, 0x30000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_16MB); + #endif + + #ifdef USE_SDRAM + #if defined(CACHE_MODE_WRITE_THROUGH) && CACHE_MODE_WRITE_THROUGH + /* Region 9 setting: Memory with Normal type, not shareable, write through */ + MPU->RBAR = ARM_MPU_RBAR(9, 0x80000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_64MB); + #else + /* Region 9 setting: Memory with Normal type, not shareable, outer/inner write back */ + MPU->RBAR = ARM_MPU_RBAR(9, 0x80000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64MB); + #endif + #endif + + while ((size >> i) > 0x1U) { + i++; + } + + if (i != 0) { + /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ + assert(!(nonCacheStart % size)); + assert(size == (uint32_t) (1 << i)); + assert(i >= 5); + + /* Region 10 setting: Memory with Normal type, not shareable, non-cacheable */ + MPU->RBAR = ARM_MPU_RBAR(10, nonCacheStart); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1); + } + + /* Region 11 setting: Memory with Device type, not shareable, non-cacheable */ + MPU->RBAR = ARM_MPU_RBAR(11, 0x40000000); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_16MB); + + /* Region 12 setting: Memory with Device type, not shareable, non-cacheable */ + MPU->RBAR = ARM_MPU_RBAR(12, 0x41000000); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_2MB); + + /* Region 13 setting: Memory with Device type, not shareable, non-cacheable */ + MPU->RBAR = ARM_MPU_RBAR(13, 0x41400000); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1MB); + + /* Region 14 setting: Memory with Device type, not shareable, non-cacheable */ + MPU->RBAR = ARM_MPU_RBAR(14, 0x41800000); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_2MB); + + /* Region 15 setting: Memory with Device type, not shareable, non-cacheable */ + MPU->RBAR = ARM_MPU_RBAR(15, 0x42000000); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1MB); + + /* Enable MPU */ + ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk); + + /* Enable I cache and D cache */ + #if defined(__DCACHE_PRESENT) && __DCACHE_PRESENT + SCB_EnableDCache(); + #endif + #if defined(__ICACHE_PRESENT) && __ICACHE_PRESENT + SCB_EnableICache(); + #endif +} + +#elif __CORTEX_M == 4 + +static void BOARD_ConfigMPU(void) { + #if defined(__CC_ARM) || defined(__ARMCC_VERSION) + extern uint32_t Image$$RW_m_ncache$$Base[]; + /* RW_m_ncache_unused is a auxiliary region which is used to get the whole size of noncache section */ + extern uint32_t Image$$RW_m_ncache_unused$$Base[]; + extern uint32_t Image$$RW_m_ncache_unused$$ZI$$Limit[]; + uint32_t nonCacheStart = (uint32_t) Image$$RW_m_ncache$$Base; + uint32_t nonCacheSize = ((uint32_t) Image$$RW_m_ncache_unused$$Base == nonCacheStart) ? 0 : ((uint32_t) Image$$RW_m_ncache_unused$$ZI$$Limit - nonCacheStart); + #elif defined(__MCUXPRESSO) + extern uint32_t __base_NCACHE_REGION; + extern uint32_t __top_NCACHE_REGION; + uint32_t nonCacheStart = (uint32_t) (&__base_NCACHE_REGION); + uint32_t nonCacheSize = (uint32_t) (&__top_NCACHE_REGION) - nonCacheStart; + #elif defined(__ICCARM__) || defined(__GNUC__) + extern uint32_t __NCACHE_REGION_START[]; + extern uint32_t __NCACHE_REGION_SIZE[]; + uint32_t nonCacheStart = (uint32_t) __NCACHE_REGION_START; + uint32_t nonCacheSize = (uint32_t) __NCACHE_REGION_SIZE; + #endif + #if defined(__USE_SHMEM) + #if defined(__CC_ARM) || defined(__ARMCC_VERSION) + extern uint32_t Image$$RPMSG_SH_MEM$$Base[]; + /* RPMSG_SH_MEM_unused is a auxiliary region which is used to get the whole size of RPMSG_SH_MEM section */ + extern uint32_t Image$$RPMSG_SH_MEM_unused$$Base[]; + extern uint32_t Image$$RPMSG_SH_MEM_unused$$ZI$$Limit[]; + uint32_t rpmsgShmemStart = (uint32_t) Image$$RPMSG_SH_MEM$$Base; + uint32_t rpmsgShmemSize = (uint32_t) Image$$RPMSG_SH_MEM_unused$$ZI$$Limit - rpmsgShmemStart; + #elif defined(__MCUXPRESSO) + extern uint32_t __base_rpmsg_sh_mem; + extern uint32_t __top_rpmsg_sh_mem; + uint32_t rpmsgShmemStart = (uint32_t) (&__base_rpmsg_sh_mem); + uint32_t rpmsgShmemSize = (uint32_t) (&__top_rpmsg_sh_mem) - rpmsgShmemStart; + #elif defined(__ICCARM__) || defined(__GNUC__) + extern uint32_t __RPMSG_SH_MEM_START[]; + extern uint32_t __RPMSG_SH_MEM_SIZE[]; + uint32_t rpmsgShmemStart = (uint32_t) __RPMSG_SH_MEM_START; + uint32_t rpmsgShmemSize = (uint32_t) __RPMSG_SH_MEM_SIZE; + #endif + #endif + uint32_t i = 0; + + /* Only config non-cacheable region on system bus */ + assert(nonCacheStart >= 0x20000000); + + /* Disable code bus cache */ + if (LMEM_PCCCR_ENCACHE_MASK == (LMEM_PCCCR_ENCACHE_MASK & LMEM->PCCCR)) { + /* Enable the processor code bus to push all modified lines. */ + LMEM->PCCCR |= LMEM_PCCCR_PUSHW0_MASK | LMEM_PCCCR_PUSHW1_MASK | LMEM_PCCCR_GO_MASK; + /* Wait until the cache command completes. */ + while ((LMEM->PCCCR & LMEM_PCCCR_GO_MASK) != 0U) { + } + /* As a precaution clear the bits to avoid inadvertently re-running this command. */ + LMEM->PCCCR &= ~(LMEM_PCCCR_PUSHW0_MASK | LMEM_PCCCR_PUSHW1_MASK); + /* Now disable the cache. */ + LMEM->PCCCR &= ~LMEM_PCCCR_ENCACHE_MASK; + } + + /* Disable system bus cache */ + if (LMEM_PSCCR_ENCACHE_MASK == (LMEM_PSCCR_ENCACHE_MASK & LMEM->PSCCR)) { + /* Enable the processor system bus to push all modified lines. */ + LMEM->PSCCR |= LMEM_PSCCR_PUSHW0_MASK | LMEM_PSCCR_PUSHW1_MASK | LMEM_PSCCR_GO_MASK; + /* Wait until the cache command completes. */ + while ((LMEM->PSCCR & LMEM_PSCCR_GO_MASK) != 0U) { + } + /* As a precaution clear the bits to avoid inadvertently re-running this command. */ + LMEM->PSCCR &= ~(LMEM_PSCCR_PUSHW0_MASK | LMEM_PSCCR_PUSHW1_MASK); + /* Now disable the cache. */ + LMEM->PSCCR &= ~LMEM_PSCCR_ENCACHE_MASK; + } + + /* Disable MPU */ + ARM_MPU_Disable(); + + #if defined(CACHE_MODE_WRITE_THROUGH) && CACHE_MODE_WRITE_THROUGH + /* Region 0 setting: Memory with Normal type, not shareable, write through */ + MPU->RBAR = ARM_MPU_RBAR(0, 0x20200000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_1MB); + + /* Region 1 setting: Memory with Normal type, not shareable, write through */ + MPU->RBAR = ARM_MPU_RBAR(1, 0x20300000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_512KB); + + /* Region 2 setting: Memory with Normal type, not shareable, write through */ + MPU->RBAR = ARM_MPU_RBAR(2, 0x80000000U); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_64MB); + + while ((nonCacheSize >> i) > 0x1U) { + i++; + } + + if (i != 0) { + /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ + assert(!(nonCacheStart % nonCacheSize)); + assert(nonCacheSize == (uint32_t) (1 << i)); + assert(i >= 5); + + /* Region 3 setting: Memory with device type, not shareable, non-cacheable */ + MPU->RBAR = ARM_MPU_RBAR(3, nonCacheStart); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1); + } + + #if defined(__USE_SHMEM) + i = 0; + + while ((rpmsgShmemSize >> i) > 0x1U) { + i++; + } + + if (i != 0) { + /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ + assert(!(rpmsgShmemStart % rpmsgShmemSize)); + assert(rpmsgShmemSize == (uint32_t) (1 << i)); + assert(i >= 5); + + /* Region 4 setting: Memory with device type, not shareable, non-cacheable */ + MPU->RBAR = ARM_MPU_RBAR(4, rpmsgShmemStart); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1); + } + #endif + #else + while ((nonCacheSize >> i) > 0x1U) { + i++; + } + + if (i != 0) { + /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ + assert(!(nonCacheStart % nonCacheSize)); + assert(nonCacheSize == (uint32_t) (1 << i)); + assert(i >= 5); + + /* Region 0 setting: Memory with device type, not shareable, non-cacheable */ + MPU->RBAR = ARM_MPU_RBAR(0, nonCacheStart); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1); + } + + #if defined(__USE_SHMEM) + i = 0; + + while ((rpmsgShmemSize >> i) > 0x1U) { + i++; + } + + if (i != 0) { + /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ + assert(!(rpmsgShmemStart % rpmsgShmemSize)); + assert(rpmsgShmemSize == (uint32_t) (1 << i)); + assert(i >= 5); + + /* Region 1 setting: Memory with device type, not shareable, non-cacheable */ + MPU->RBAR = ARM_MPU_RBAR(1, rpmsgShmemStart); + MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1); + } + #endif + #endif + + /* Enable MPU */ + ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk); + + /* Enables the processor system bus to invalidate all lines in both ways. + and Initiate the processor system bus cache command. */ + LMEM->PSCCR |= LMEM_PSCCR_INVW0_MASK | LMEM_PSCCR_INVW1_MASK | LMEM_PSCCR_GO_MASK; + /* Wait until the cache command completes */ + while ((LMEM->PSCCR & LMEM_PSCCR_GO_MASK) != 0U) { + } + /* As a precaution clear the bits to avoid inadvertently re-running this command. */ + LMEM->PSCCR &= ~(LMEM_PSCCR_INVW0_MASK | LMEM_PSCCR_INVW1_MASK); + /* Now enable the system bus cache. */ + LMEM->PSCCR |= LMEM_PSCCR_ENCACHE_MASK; + + /* Enables the processor code bus to invalidate all lines in both ways. + and Initiate the processor code bus code cache command. */ + LMEM->PCCCR |= LMEM_PCCCR_INVW0_MASK | LMEM_PCCCR_INVW1_MASK | LMEM_PCCCR_GO_MASK; + /* Wait until the cache command completes. */ + while ((LMEM->PCCCR & LMEM_PCCCR_GO_MASK) != 0U) { + } + /* As a precaution clear the bits to avoid inadvertently re-running this command. */ + LMEM->PCCCR &= ~(LMEM_PCCCR_INVW0_MASK | LMEM_PCCCR_INVW1_MASK); + /* Now enable the code bus cache. */ + LMEM->PCCCR |= LMEM_PCCCR_ENCACHE_MASK; +} +#endif + +static void board_init2() { + BOARD_ConfigMPU(); +} + #endif diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c index 7e4734a66..1bbd3400a 100644 --- a/hw/bsp/imxrt/family.c +++ b/hw/bsp/imxrt/family.c @@ -61,8 +61,6 @@ - Define CFG_TUSB_MEM_SECTION=__attribute__((section("NonCacheable"))) */ -// static void BOARD_ConfigMPU(void); - // needed by fsl_flexspi_nor_boot TU_ATTR_USED const uint8_t dcd_data[] = {0x00}; @@ -109,11 +107,15 @@ static void init_usb_phy(uint8_t usb_id) { } void board_init(void) { - // BOARD_ConfigMPU(); BOARD_InitBootPins(); BOARD_BootClockRUN(); SystemCoreClockUpdate(); + // Additional board init +#if defined(BOARD_INIT_2) && BOARD_INIT_2 + board_init2(); +#endif + #ifdef TRACE_ETM //CLOCK_EnableClock(kCLOCK_Trace); #endif @@ -254,387 +256,3 @@ void _exit(int __status) { } #endif #endif - -//-------------------------------------------------------------------- -// MPU configuration -//-------------------------------------------------------------------- -#if 0 // TODO move to per board specific -#if __CORTEX_M == 7 -static void BOARD_ConfigMPU(void) { - #if defined(__CC_ARM) || defined(__ARMCC_VERSION) - extern uint32_t Image$$RW_m_ncache$$Base[]; - /* RW_m_ncache_unused is a auxiliary region which is used to get the whole size of noncache section */ - extern uint32_t Image$$RW_m_ncache_unused$$Base[]; - extern uint32_t Image$$RW_m_ncache_unused$$ZI$$Limit[]; - uint32_t nonCacheStart = (uint32_t) Image$$RW_m_ncache$$Base; - uint32_t size = ((uint32_t) Image$$RW_m_ncache_unused$$Base == nonCacheStart) ? 0 : ((uint32_t) Image$$RW_m_ncache_unused$$ZI$$Limit - nonCacheStart); - #elif defined(__MCUXPRESSO) - #if defined(__USE_SHMEM) - extern uint32_t __base_rpmsg_sh_mem; - extern uint32_t __top_rpmsg_sh_mem; - uint32_t nonCacheStart = (uint32_t) (&__base_rpmsg_sh_mem); - uint32_t size = (uint32_t) (&__top_rpmsg_sh_mem) - nonCacheStart; - #else - extern uint32_t __base_NCACHE_REGION; - extern uint32_t __top_NCACHE_REGION; - uint32_t nonCacheStart = (uint32_t) (&__base_NCACHE_REGION); - uint32_t size = (uint32_t) (&__top_NCACHE_REGION) - nonCacheStart; - #endif - #elif defined(__ICCARM__) || defined(__GNUC__) - extern uint32_t __NCACHE_REGION_START[]; - extern uint32_t __NCACHE_REGION_SIZE[]; - uint32_t nonCacheStart = (uint32_t) __NCACHE_REGION_START; - uint32_t size = (uint32_t) __NCACHE_REGION_SIZE; - #endif - volatile uint32_t i = 0; - - #if defined(__ICACHE_PRESENT) && __ICACHE_PRESENT - /* Disable I cache and D cache */ - if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR)) { - SCB_DisableICache(); - } - #endif - #if defined(__DCACHE_PRESENT) && __DCACHE_PRESENT - if (SCB_CCR_DC_Msk == (SCB_CCR_DC_Msk & SCB->CCR)) { - SCB_DisableDCache(); - } - #endif - - /* Disable MPU */ - ARM_MPU_Disable(); - - /* MPU configure: - * Use ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, - * SubRegionDisable, Size) - * API in mpu_armv7.h. - * param DisableExec Instruction access (XN) disable bit,0=instruction fetches enabled, 1=instruction fetches - * disabled. - * param AccessPermission Data access permissions, allows you to configure read/write access for User and - * Privileged mode. - * Use MACROS defined in mpu_armv7.h: - * ARM_MPU_AP_NONE/ARM_MPU_AP_PRIV/ARM_MPU_AP_URO/ARM_MPU_AP_FULL/ARM_MPU_AP_PRO/ARM_MPU_AP_RO - * Combine TypeExtField/IsShareable/IsCacheable/IsBufferable to configure MPU memory access attributes. - * TypeExtField IsShareable IsCacheable IsBufferable Memory Attribute Shareability Cache - * 0 x 0 0 Strongly Ordered shareable - * 0 x 0 1 Device shareable - * 0 0 1 0 Normal not shareable Outer and inner write - * through no write allocate - * 0 0 1 1 Normal not shareable Outer and inner write - * back no write allocate - * 0 1 1 0 Normal shareable Outer and inner write - * through no write allocate - * 0 1 1 1 Normal shareable Outer and inner write - * back no write allocate - * 1 0 0 0 Normal not shareable outer and inner - * noncache - * 1 1 0 0 Normal shareable outer and inner - * noncache - * 1 0 1 1 Normal not shareable outer and inner write - * back write/read acllocate - * 1 1 1 1 Normal shareable outer and inner write - * back write/read acllocate - * 2 x 0 0 Device not shareable - * Above are normal use settings, if your want to see more details or want to config different inner/outer cache - * policy. - * please refer to Table 4-55 /4-56 in arm cortex-M7 generic user guide - * param SubRegionDisable Sub-region disable field. 0=sub-region is enabled, 1=sub-region is disabled. - * param Size Region size of the region to be configured. use ARM_MPU_REGION_SIZE_xxx MACRO in - * mpu_armv7.h. - */ - - /* - * Add default region to deny access to whole address space to workaround speculative prefetch. - * Refer to Arm errata 1013783-B for more details. - * - */ - /* Region 0 setting: Instruction access disabled, No data access permission. */ - MPU->RBAR = ARM_MPU_RBAR(0, 0x00000000U); - MPU->RASR = ARM_MPU_RASR(1, ARM_MPU_AP_NONE, 0, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_4GB); - - /* Region 1 setting: Memory with Device type, not shareable, non-cacheable. */ - MPU->RBAR = ARM_MPU_RBAR(1, 0x80000000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB); - - /* Region 2 setting: Memory with Device type, not shareable, non-cacheable. */ - MPU->RBAR = ARM_MPU_RBAR(2, 0x60000000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_512MB); - - /* Region 3 setting: Memory with Device type, not shareable, non-cacheable. */ - MPU->RBAR = ARM_MPU_RBAR(3, 0x00000000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1GB); - - /* Region 4 setting: Memory with Normal type, not shareable, outer/inner write back */ - MPU->RBAR = ARM_MPU_RBAR(4, 0x00000000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB); - - /* Region 5 setting: Memory with Normal type, not shareable, outer/inner write back */ - MPU->RBAR = ARM_MPU_RBAR(5, 0x20000000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB); - - #if defined(CACHE_MODE_WRITE_THROUGH) && CACHE_MODE_WRITE_THROUGH - /* Region 6 setting: Memory with Normal type, not shareable, write through */ - MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_1MB); - - /* Region 7 setting: Memory with Normal type, not shareable, write through */ - MPU->RBAR = ARM_MPU_RBAR(7, 0x20300000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_512KB); - #else - /* Region 6 setting: Memory with Normal type, not shareable, outer/inner write back */ - MPU->RBAR = ARM_MPU_RBAR(6, 0x20200000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_1MB); - - /* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */ - MPU->RBAR = ARM_MPU_RBAR(7, 0x20300000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_512KB); - #endif - - #if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1) - /* Region 8 setting: Memory with Normal type, not shareable, outer/inner write back. */ - MPU->RBAR = ARM_MPU_RBAR(8, 0x30000000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_16MB); - #endif - - #ifdef USE_SDRAM - #if defined(CACHE_MODE_WRITE_THROUGH) && CACHE_MODE_WRITE_THROUGH - /* Region 9 setting: Memory with Normal type, not shareable, write through */ - MPU->RBAR = ARM_MPU_RBAR(9, 0x80000000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_64MB); - #else - /* Region 9 setting: Memory with Normal type, not shareable, outer/inner write back */ - MPU->RBAR = ARM_MPU_RBAR(9, 0x80000000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64MB); - #endif - #endif - - while ((size >> i) > 0x1U) { - i++; - } - - if (i != 0) { - /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ - assert(!(nonCacheStart % size)); - assert(size == (uint32_t) (1 << i)); - assert(i >= 5); - - /* Region 10 setting: Memory with Normal type, not shareable, non-cacheable */ - MPU->RBAR = ARM_MPU_RBAR(10, nonCacheStart); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1); - } - - /* Region 11 setting: Memory with Device type, not shareable, non-cacheable */ - MPU->RBAR = ARM_MPU_RBAR(11, 0x40000000); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_16MB); - - /* Region 12 setting: Memory with Device type, not shareable, non-cacheable */ - MPU->RBAR = ARM_MPU_RBAR(12, 0x41000000); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_2MB); - - /* Region 13 setting: Memory with Device type, not shareable, non-cacheable */ - MPU->RBAR = ARM_MPU_RBAR(13, 0x41400000); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1MB); - - /* Region 14 setting: Memory with Device type, not shareable, non-cacheable */ - MPU->RBAR = ARM_MPU_RBAR(14, 0x41800000); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_2MB); - - /* Region 15 setting: Memory with Device type, not shareable, non-cacheable */ - MPU->RBAR = ARM_MPU_RBAR(15, 0x42000000); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_1MB); - - /* Enable MPU */ - ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk); - - /* Enable I cache and D cache */ - #if defined(__DCACHE_PRESENT) && __DCACHE_PRESENT - SCB_EnableDCache(); - #endif - #if defined(__ICACHE_PRESENT) && __ICACHE_PRESENT - SCB_EnableICache(); - #endif -} - -#elif __CORTEX_M == 4 - -static void BOARD_ConfigMPU(void) { - #if defined(__CC_ARM) || defined(__ARMCC_VERSION) - extern uint32_t Image$$RW_m_ncache$$Base[]; - /* RW_m_ncache_unused is a auxiliary region which is used to get the whole size of noncache section */ - extern uint32_t Image$$RW_m_ncache_unused$$Base[]; - extern uint32_t Image$$RW_m_ncache_unused$$ZI$$Limit[]; - uint32_t nonCacheStart = (uint32_t) Image$$RW_m_ncache$$Base; - uint32_t nonCacheSize = ((uint32_t) Image$$RW_m_ncache_unused$$Base == nonCacheStart) ? 0 : ((uint32_t) Image$$RW_m_ncache_unused$$ZI$$Limit - nonCacheStart); - #elif defined(__MCUXPRESSO) - extern uint32_t __base_NCACHE_REGION; - extern uint32_t __top_NCACHE_REGION; - uint32_t nonCacheStart = (uint32_t) (&__base_NCACHE_REGION); - uint32_t nonCacheSize = (uint32_t) (&__top_NCACHE_REGION) - nonCacheStart; - #elif defined(__ICCARM__) || defined(__GNUC__) - extern uint32_t __NCACHE_REGION_START[]; - extern uint32_t __NCACHE_REGION_SIZE[]; - uint32_t nonCacheStart = (uint32_t) __NCACHE_REGION_START; - uint32_t nonCacheSize = (uint32_t) __NCACHE_REGION_SIZE; - #endif - #if defined(__USE_SHMEM) - #if defined(__CC_ARM) || defined(__ARMCC_VERSION) - extern uint32_t Image$$RPMSG_SH_MEM$$Base[]; - /* RPMSG_SH_MEM_unused is a auxiliary region which is used to get the whole size of RPMSG_SH_MEM section */ - extern uint32_t Image$$RPMSG_SH_MEM_unused$$Base[]; - extern uint32_t Image$$RPMSG_SH_MEM_unused$$ZI$$Limit[]; - uint32_t rpmsgShmemStart = (uint32_t) Image$$RPMSG_SH_MEM$$Base; - uint32_t rpmsgShmemSize = (uint32_t) Image$$RPMSG_SH_MEM_unused$$ZI$$Limit - rpmsgShmemStart; - #elif defined(__MCUXPRESSO) - extern uint32_t __base_rpmsg_sh_mem; - extern uint32_t __top_rpmsg_sh_mem; - uint32_t rpmsgShmemStart = (uint32_t) (&__base_rpmsg_sh_mem); - uint32_t rpmsgShmemSize = (uint32_t) (&__top_rpmsg_sh_mem) - rpmsgShmemStart; - #elif defined(__ICCARM__) || defined(__GNUC__) - extern uint32_t __RPMSG_SH_MEM_START[]; - extern uint32_t __RPMSG_SH_MEM_SIZE[]; - uint32_t rpmsgShmemStart = (uint32_t) __RPMSG_SH_MEM_START; - uint32_t rpmsgShmemSize = (uint32_t) __RPMSG_SH_MEM_SIZE; - #endif - #endif - uint32_t i = 0; - - /* Only config non-cacheable region on system bus */ - assert(nonCacheStart >= 0x20000000); - - /* Disable code bus cache */ - if (LMEM_PCCCR_ENCACHE_MASK == (LMEM_PCCCR_ENCACHE_MASK & LMEM->PCCCR)) { - /* Enable the processor code bus to push all modified lines. */ - LMEM->PCCCR |= LMEM_PCCCR_PUSHW0_MASK | LMEM_PCCCR_PUSHW1_MASK | LMEM_PCCCR_GO_MASK; - /* Wait until the cache command completes. */ - while ((LMEM->PCCCR & LMEM_PCCCR_GO_MASK) != 0U) { - } - /* As a precaution clear the bits to avoid inadvertently re-running this command. */ - LMEM->PCCCR &= ~(LMEM_PCCCR_PUSHW0_MASK | LMEM_PCCCR_PUSHW1_MASK); - /* Now disable the cache. */ - LMEM->PCCCR &= ~LMEM_PCCCR_ENCACHE_MASK; - } - - /* Disable system bus cache */ - if (LMEM_PSCCR_ENCACHE_MASK == (LMEM_PSCCR_ENCACHE_MASK & LMEM->PSCCR)) { - /* Enable the processor system bus to push all modified lines. */ - LMEM->PSCCR |= LMEM_PSCCR_PUSHW0_MASK | LMEM_PSCCR_PUSHW1_MASK | LMEM_PSCCR_GO_MASK; - /* Wait until the cache command completes. */ - while ((LMEM->PSCCR & LMEM_PSCCR_GO_MASK) != 0U) { - } - /* As a precaution clear the bits to avoid inadvertently re-running this command. */ - LMEM->PSCCR &= ~(LMEM_PSCCR_PUSHW0_MASK | LMEM_PSCCR_PUSHW1_MASK); - /* Now disable the cache. */ - LMEM->PSCCR &= ~LMEM_PSCCR_ENCACHE_MASK; - } - - /* Disable MPU */ - ARM_MPU_Disable(); - - #if defined(CACHE_MODE_WRITE_THROUGH) && CACHE_MODE_WRITE_THROUGH - /* Region 0 setting: Memory with Normal type, not shareable, write through */ - MPU->RBAR = ARM_MPU_RBAR(0, 0x20200000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_1MB); - - /* Region 1 setting: Memory with Normal type, not shareable, write through */ - MPU->RBAR = ARM_MPU_RBAR(1, 0x20300000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_512KB); - - /* Region 2 setting: Memory with Normal type, not shareable, write through */ - MPU->RBAR = ARM_MPU_RBAR(2, 0x80000000U); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_64MB); - - while ((nonCacheSize >> i) > 0x1U) { - i++; - } - - if (i != 0) { - /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ - assert(!(nonCacheStart % nonCacheSize)); - assert(nonCacheSize == (uint32_t) (1 << i)); - assert(i >= 5); - - /* Region 3 setting: Memory with device type, not shareable, non-cacheable */ - MPU->RBAR = ARM_MPU_RBAR(3, nonCacheStart); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1); - } - - #if defined(__USE_SHMEM) - i = 0; - - while ((rpmsgShmemSize >> i) > 0x1U) { - i++; - } - - if (i != 0) { - /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ - assert(!(rpmsgShmemStart % rpmsgShmemSize)); - assert(rpmsgShmemSize == (uint32_t) (1 << i)); - assert(i >= 5); - - /* Region 4 setting: Memory with device type, not shareable, non-cacheable */ - MPU->RBAR = ARM_MPU_RBAR(4, rpmsgShmemStart); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1); - } - #endif - #else - while ((nonCacheSize >> i) > 0x1U) { - i++; - } - - if (i != 0) { - /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ - assert(!(nonCacheStart % nonCacheSize)); - assert(nonCacheSize == (uint32_t) (1 << i)); - assert(i >= 5); - - /* Region 0 setting: Memory with device type, not shareable, non-cacheable */ - MPU->RBAR = ARM_MPU_RBAR(0, nonCacheStart); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1); - } - - #if defined(__USE_SHMEM) - i = 0; - - while ((rpmsgShmemSize >> i) > 0x1U) { - i++; - } - - if (i != 0) { - /* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */ - assert(!(rpmsgShmemStart % rpmsgShmemSize)); - assert(rpmsgShmemSize == (uint32_t) (1 << i)); - assert(i >= 5); - - /* Region 1 setting: Memory with device type, not shareable, non-cacheable */ - MPU->RBAR = ARM_MPU_RBAR(1, rpmsgShmemStart); - MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1); - } - #endif - #endif - - /* Enable MPU */ - ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_HFNMIENA_Msk); - - /* Enables the processor system bus to invalidate all lines in both ways. - and Initiate the processor system bus cache command. */ - LMEM->PSCCR |= LMEM_PSCCR_INVW0_MASK | LMEM_PSCCR_INVW1_MASK | LMEM_PSCCR_GO_MASK; - /* Wait until the cache command completes */ - while ((LMEM->PSCCR & LMEM_PSCCR_GO_MASK) != 0U) { - } - /* As a precaution clear the bits to avoid inadvertently re-running this command. */ - LMEM->PSCCR &= ~(LMEM_PSCCR_INVW0_MASK | LMEM_PSCCR_INVW1_MASK); - /* Now enable the system bus cache. */ - LMEM->PSCCR |= LMEM_PSCCR_ENCACHE_MASK; - - /* Enables the processor code bus to invalidate all lines in both ways. - and Initiate the processor code bus code cache command. */ - LMEM->PCCCR |= LMEM_PCCCR_INVW0_MASK | LMEM_PCCCR_INVW1_MASK | LMEM_PCCCR_GO_MASK; - /* Wait until the cache command completes. */ - while ((LMEM->PCCCR & LMEM_PCCCR_GO_MASK) != 0U) { - } - /* As a precaution clear the bits to avoid inadvertently re-running this command. */ - LMEM->PCCCR &= ~(LMEM_PCCCR_INVW0_MASK | LMEM_PCCCR_INVW1_MASK); - /* Now enable the code bus cache. */ - LMEM->PCCCR |= LMEM_PCCCR_ENCACHE_MASK; -} -#endif -#endif From 4db2bdad07f55b03df8c40928a2b56536fa823e3 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Sep 2025 14:08:54 +0200 Subject: [PATCH 375/382] echi: fix NXP USBPHY disconnection detection Signed-off-by: HiFiPhile --- src/portable/ehci/ehci.c | 60 ++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index b372fe635..76b0142b2 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -38,6 +38,11 @@ #include "ehci_api.h" #include "ehci.h" +// NXP specific fixes +#if TU_CHECK_MCU(OPT_MCU_MIMXRT1XXX, OPT_MCU_LPC55, OPT_MCU_MCXN9) +#include "fsl_device_registers.h" +#endif + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -179,6 +184,36 @@ static void ehci_enable_schedule(ehci_registers_t* regs, bool is_period) { } } +#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) +static void nxp_usbphy_disconn_detector_set(uint8_t port, bool enable) { + // unify naming convention +#if !defined(USBPHY1) && defined(USBPHY) + #define USBPHY1 USBPHY +#endif + + if (port == 0) { + if (enable) { + USBPHY1->CTRL_SET = USBPHY_CTRL_ENHOSTDISCONDETECT_MASK; + } else { + USBPHY1->CTRL_CLR = USBPHY_CTRL_ENHOSTDISCONDETECT_MASK; + } + } +#if FSL_FEATURE_SOC_USBPHY_COUNT > 1U + else if (port == 1) { + if (enable) { + USBPHY2->CTRL_SET = USBPHY_CTRL_ENHOSTDISCONDETECT_MASK; + } else { + USBPHY2->CTRL_CLR = USBPHY_CTRL_ENHOSTDISCONDETECT_MASK; + } + } +#endif + +#if !defined(USBPHY1) && defined(USBPHY) + #undef USBPHY1 +#endif +} +#endif + //--------------------------------------------------------------------+ // HCD API //--------------------------------------------------------------------+ @@ -213,16 +248,21 @@ void hcd_port_reset_end(uint8_t rhport) { (void) rhport; ehci_registers_t* regs = ehci_data.regs; - // skip if reset is already complete - if (!regs->portsc_bm.port_reset) { - return; + // stop reset only if is not complete yet + if (regs->portsc_bm.port_reset) { + // mask out all change bits since they are Write 1 to clear + uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C; + portsc &= ~EHCI_PORTSC_MASK_PORT_RESET; + + regs->portsc = portsc; } - // mask out all change bits since they are Write 1 to clear - uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C; - portsc &= ~EHCI_PORTSC_MASK_PORT_RESET; - - regs->portsc = portsc; +#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) + // Enable disconnect detector for highspeed device only + if (hcd_port_speed_get(rhport) == TUSB_SPEED_HIGH) { + nxp_usbphy_disconn_detector_set(rhport, true); + } +#endif } bool hcd_port_connect_status(uint8_t rhport) { @@ -579,6 +619,10 @@ void port_connect_status_change_isr(uint8_t rhport) { hcd_event_device_attach(rhport, true); } else // device unplugged { +#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) + // Disable disconnect detector + nxp_usbphy_disconn_detector_set(rhport, false); +#endif hcd_event_device_remove(rhport, true); } } From 99bee6a900db60cf232766531e785108f50e614d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Sep 2025 14:25:44 +0200 Subject: [PATCH 376/382] ehci: fix removed qhd get reused Signed-off-by: HiFiPhile --- src/host/usbh.c | 2 +- src/portable/ehci/ehci.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 1c63ac712..d09874d6e 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -844,7 +844,7 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t const uint8_t ep_status = tu_edpt_addr(0, 1 - request->bmRequestType_bit.direction); TU_ASSERT(hcd_edpt_xfer(rhport, daddr, ep_status, NULL, 0)); break; - } + } case CONTROL_STAGE_ACK: { // Abort all pending transfers if SET_CONFIGURATION request diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index 76b0142b2..953483583 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -35,6 +35,7 @@ #include "host/hcd.h" #include "host/usbh.h" +#include "host/usbh_pvt.h" #include "ehci_api.h" #include "ehci.h" @@ -866,14 +867,21 @@ static ehci_qhd_t *qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) { } ehci_qhd_t *qhd_pool = ehci_data.qhd_pool; + + // protect qhd_pool since 'used' and 'removing' can be changed in isr + ehci_qhd_t *result = NULL; + usbh_spin_lock(false); for (uint32_t i = 0; i < QHD_MAX; i++) { if ((qhd_pool[i].dev_addr == dev_addr) && - ep_addr == qhd_ep_addr(&qhd_pool[i])) { - return &qhd_pool[i]; + ep_addr == qhd_ep_addr(&qhd_pool[i]) && + qhd_pool[i].used && !qhd_pool[i].removing) { + result = &qhd_pool[i]; + break; } } + usbh_spin_unlock(false); - return NULL; + return result; } // Init queue head with endpoint descriptor From 7810b5816123b0bb4deed27a0367c91919d39238 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Sep 2025 16:37:33 +0200 Subject: [PATCH 377/382] exclude stm32l0538 due to size limit Signed-off-by: HiFiPhile --- examples/device/audio_test_freertos/skip.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/device/audio_test_freertos/skip.txt b/examples/device/audio_test_freertos/skip.txt index 650bf355b..1f3d4281a 100644 --- a/examples/device/audio_test_freertos/skip.txt +++ b/examples/device/audio_test_freertos/skip.txt @@ -14,3 +14,4 @@ mcu:VALENTYUSB_EPTRI mcu:RAXXX family:broadcom_32bit family:broadcom_64bit +board:stm32l0538disco From 8515e47ad9980f8ad380913bda72425b1bb83648 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Sep 2025 16:49:55 +0200 Subject: [PATCH 378/382] Update comment Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/fsdev_stm32.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h index 770baa05a..95f40269a 100644 --- a/src/portable/st/stm32_fsdev/fsdev_stm32.h +++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h @@ -268,7 +268,10 @@ #endif #ifndef CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP - // Defaults to double-buffered isochronous endpoints on devices with >1KB PMA + // Default configuration for double-buffered isochronous endpoints: + // - Enable double buffering on devices with >1KB Packet Memory Area (PMA) + // to improve isochronous transfer reliability and performance + // - Disable on devices with limited PMA to conserve memory space #if FSDEV_PMA_SIZE > 1024u #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 1 #else @@ -277,12 +280,16 @@ #endif #if FSDEV_HAS_SBUF_ISO != 0 && CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP == 0 - // If hardware has SBUF_ISO bit single-buffered endpoints consume only - // one half of endpoint pair register. + // SBUF_ISO configuration: + // - Some STM32 devices have special hardware support for single-buffered isochronous endpoints + // - When SBUF_ISO bit is available and double buffering is disabled: + // Enable SBUF_ISO to optimize endpoint register usage (one half of endpoint pair register) #define FSDEV_USE_SBUF_ISO 1 #else - // Otherwise it consumes entire endpoint pair but we can at least save - // memory by configuring the same buffer twice. + // When either: + // - Hardware doesn't support SBUF_ISO feature, or + // - Double buffering is enabled for isochronous endpoints + // We must use the entire endpoint pair register #define FSDEV_USE_SBUF_ISO 0 #endif From cf6cbf0d1aca1985dcc8d1b88279028ec044e7a8 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 12 Sep 2025 21:30:53 +0200 Subject: [PATCH 379/382] Fix AT32 compile after #3152 Signed-off-by: HiFiPhile --- src/portable/st/stm32_fsdev/fsdev_at32.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h index 3a785bbbd..f7ee89995 100644 --- a/src/portable/st/stm32_fsdev/fsdev_at32.h +++ b/src/portable/st/stm32_fsdev/fsdev_at32.h @@ -36,9 +36,14 @@ #endif #define FSDEV_PMA_SIZE (512u) +#define FSDEV_USE_SBUF_ISO 0 #define FSDEV_REG_BASE (APB1PERIPH_BASE + 0x00005C00UL) #define FSDEV_PMA_BASE (APB1PERIPH_BASE + 0x00006000UL) +#ifndef CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP + #define CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP 0 +#endif + /**************************** ISTR interrupt events *************************/ #define USB_ISTR_CTR ((uint16_t)0x8000U) /*!< Correct TRansfer (clear-only bit) */ #define USB_ISTR_PMAOVR ((uint16_t)0x4000U) /*!< DMA OVeR/underrun (clear-only bit) */ From cc19c02f860f96299ceccdfcaf1befb308c9fab8 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Sep 2025 15:47:06 +0700 Subject: [PATCH 380/382] dwc2: wait for ahb idle before core reset --- .idea/debugServers/AT32F423VCT7.xml | 13 +++++++++++++ .idea/debugServers/ST_LINK.xml | 13 +++++++++++++ .idea/debugServers/at32f403acgu7.xml | 13 +++++++++++++ .idea/debugServers/max32690.xml | 13 +++++++++++++ .idea/debugServers/s3.xml | 6 ++++++ .idea/debugServers/wch_riscv.xml | 14 ++++++++++++++ src/common/tusb_common.h | 4 ++-- src/portable/synopsys/dwc2/dwc2_common.c | 16 +++++++++++----- 8 files changed, 85 insertions(+), 7 deletions(-) create mode 100644 .idea/debugServers/AT32F423VCT7.xml create mode 100644 .idea/debugServers/ST_LINK.xml create mode 100644 .idea/debugServers/at32f403acgu7.xml create mode 100644 .idea/debugServers/max32690.xml create mode 100644 .idea/debugServers/s3.xml create mode 100644 .idea/debugServers/wch_riscv.xml diff --git a/.idea/debugServers/AT32F423VCT7.xml b/.idea/debugServers/AT32F423VCT7.xml new file mode 100644 index 000000000..38b3d76ef --- /dev/null +++ b/.idea/debugServers/AT32F423VCT7.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/ST_LINK.xml b/.idea/debugServers/ST_LINK.xml new file mode 100644 index 000000000..7c21d3879 --- /dev/null +++ b/.idea/debugServers/ST_LINK.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/at32f403acgu7.xml b/.idea/debugServers/at32f403acgu7.xml new file mode 100644 index 000000000..9df65140f --- /dev/null +++ b/.idea/debugServers/at32f403acgu7.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/max32690.xml b/.idea/debugServers/max32690.xml new file mode 100644 index 000000000..3551f591e --- /dev/null +++ b/.idea/debugServers/max32690.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/s3.xml b/.idea/debugServers/s3.xml new file mode 100644 index 000000000..a03abf744 --- /dev/null +++ b/.idea/debugServers/s3.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/debugServers/wch_riscv.xml b/.idea/debugServers/wch_riscv.xml new file mode 100644 index 000000000..2e147f1b6 --- /dev/null +++ b/.idea/debugServers/wch_riscv.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 1fb93da11..e35d3e6fe 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -168,8 +168,8 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_high(uint16_t ui16) { return TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_u16_low (uint16_t ui16) { return TU_U16_LOW(ui16); } //------------- Bits -------------// -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_clear(uint32_t value, uint8_t pos) { return value & (~TU_BIT(pos)); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_set (uint32_t value, uint8_t pos) { return value | TU_BIT(pos); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_bit_clear(uint32_t value, uint8_t pos) { return value & (~TU_BIT(pos)); } TU_ATTR_ALWAYS_INLINE static inline bool tu_bit_test (uint32_t value, uint8_t pos) { return (value & TU_BIT(pos)) ? true : false; } //------------- Min -------------// diff --git a/src/portable/synopsys/dwc2/dwc2_common.c b/src/portable/synopsys/dwc2/dwc2_common.c index d7d157149..5ff18ab94 100644 --- a/src/portable/synopsys/dwc2/dwc2_common.c +++ b/src/portable/synopsys/dwc2/dwc2_common.c @@ -45,20 +45,26 @@ // //-------------------------------------------------------------------- static void reset_core(dwc2_regs_t* dwc2) { + // The software must check that bit 31 in this register is set to 1 (AHB Master is Idle) before starting any operation + while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) { + } + // load gsnpsid (it is not readable after reset is asserted) - uint32_t gsnpsid = dwc2->gsnpsid; + const uint32_t gsnpsid = dwc2->gsnpsid; // reset core dwc2->grstctl |= GRSTCTL_CSRST; if ((gsnpsid & DWC2_CORE_REV_MASK) < (DWC2_CORE_REV_4_20a & DWC2_CORE_REV_MASK)) { - // prior v4.20a CSRST is self-clearing + // prior v4.20a: CSRST is self-clearing and the core clears this bit after all the necessary logic is reset in + // the core, which can take several clocks, depending on the current state of the core. Once this bit has been + // cleared, the software must wait at least 3 PHY clocks before accessing the PHY domain (synchronization delay). while (dwc2->grstctl & GRSTCTL_CSRST) {} } else { - // From v4.20a CSRST bit is write only, CSRT_DONE (w1c) is introduced for checking. - // CSRST must also be explicitly cleared + // From v4.20a: CSRST bit is write only. The application must clear this bit after checking the bit 29 of this + // register i.e Core Soft Reset Done CSRT_DONE (w1c) while (!(dwc2->grstctl & GRSTCTL_CSRST_DONE)) {} - dwc2->grstctl = (dwc2->grstctl & ~GRSTCTL_CSRST) | GRSTCTL_CSRST_DONE; + dwc2->grstctl = (dwc2->grstctl & ~GRSTCTL_CSRST) | GRSTCTL_CSRST_DONE; } while (!(dwc2->grstctl & GRSTCTL_AHBIDL)) {} // wait for AHB master IDLE From 65220679d641b2b3cde1000b196a411d031d2744 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Sep 2025 16:15:48 +0700 Subject: [PATCH 381/382] fix imxrt build --- hw/bsp/imxrt/boards/metro_m7_1011/board.h | 3 +++ hw/bsp/imxrt/boards/metro_m7_1011_sd/board.h | 3 +++ hw/bsp/imxrt/boards/mimxrt1010_evk/board.h | 3 +++ hw/bsp/imxrt/boards/mimxrt1015_evk/board.h | 3 +++ hw/bsp/imxrt/boards/mimxrt1020_evk/board.h | 3 +++ hw/bsp/imxrt/boards/mimxrt1024_evk/board.h | 3 +++ hw/bsp/imxrt/boards/mimxrt1050_evkb/board.h | 3 +++ hw/bsp/imxrt/boards/mimxrt1060_evk/board.h | 3 +++ hw/bsp/imxrt/boards/mimxrt1064_evk/board.h | 3 +++ hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h | 8 +------- hw/bsp/imxrt/boards/teensy_40/board.h | 3 +++ hw/bsp/imxrt/boards/teensy_41/board.h | 3 +++ hw/bsp/imxrt/family.c | 5 +---- 13 files changed, 35 insertions(+), 11 deletions(-) diff --git a/hw/bsp/imxrt/boards/metro_m7_1011/board.h b/hw/bsp/imxrt/boards/metro_m7_1011/board.h index ccc4d6b9a..908b9b87c 100644 --- a/hw/bsp/imxrt/boards/metro_m7_1011/board.h +++ b/hw/bsp/imxrt/boards/metro_m7_1011/board.h @@ -49,4 +49,7 @@ #define UART_PORT LPUART1 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_UART_CLK_ROOT +static inline void BOARD_ConfigMPU(void) { +} + #endif diff --git a/hw/bsp/imxrt/boards/metro_m7_1011_sd/board.h b/hw/bsp/imxrt/boards/metro_m7_1011_sd/board.h index 04d5b01b5..8f100284a 100644 --- a/hw/bsp/imxrt/boards/metro_m7_1011_sd/board.h +++ b/hw/bsp/imxrt/boards/metro_m7_1011_sd/board.h @@ -49,4 +49,7 @@ #define UART_PORT LPUART1 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_UART_CLK_ROOT +static inline void BOARD_ConfigMPU(void) { +} + #endif diff --git a/hw/bsp/imxrt/boards/mimxrt1010_evk/board.h b/hw/bsp/imxrt/boards/mimxrt1010_evk/board.h index 6b9ec0ae1..eda185fe4 100644 --- a/hw/bsp/imxrt/boards/mimxrt1010_evk/board.h +++ b/hw/bsp/imxrt/boards/mimxrt1010_evk/board.h @@ -49,4 +49,7 @@ #define UART_PORT LPUART1 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_UART_CLK_ROOT +static inline void BOARD_ConfigMPU(void) { +} + #endif diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/board.h b/hw/bsp/imxrt/boards/mimxrt1015_evk/board.h index e2ec4e627..697b9c30b 100644 --- a/hw/bsp/imxrt/boards/mimxrt1015_evk/board.h +++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/board.h @@ -53,4 +53,7 @@ #define UART_RX_PINMUX IOMUXC_GPIO_AD_B0_07_LPUART1_RX #define UART_TX_PINMUX IOMUXC_GPIO_AD_B0_06_LPUART1_TX +static inline void BOARD_ConfigMPU(void) { +} + #endif diff --git a/hw/bsp/imxrt/boards/mimxrt1020_evk/board.h b/hw/bsp/imxrt/boards/mimxrt1020_evk/board.h index 3f9c97e11..5028a6239 100644 --- a/hw/bsp/imxrt/boards/mimxrt1020_evk/board.h +++ b/hw/bsp/imxrt/boards/mimxrt1020_evk/board.h @@ -49,4 +49,7 @@ #define UART_PORT LPUART1 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_UART_CLK_ROOT +static inline void BOARD_ConfigMPU(void) { +} + #endif diff --git a/hw/bsp/imxrt/boards/mimxrt1024_evk/board.h b/hw/bsp/imxrt/boards/mimxrt1024_evk/board.h index 39e63c472..f6a97815e 100644 --- a/hw/bsp/imxrt/boards/mimxrt1024_evk/board.h +++ b/hw/bsp/imxrt/boards/mimxrt1024_evk/board.h @@ -50,4 +50,7 @@ #define UART_PORT LPUART1 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_UART_CLK_ROOT +static inline void BOARD_ConfigMPU(void) { +} + #endif diff --git a/hw/bsp/imxrt/boards/mimxrt1050_evkb/board.h b/hw/bsp/imxrt/boards/mimxrt1050_evkb/board.h index de7ab0535..47678e9fe 100644 --- a/hw/bsp/imxrt/boards/mimxrt1050_evkb/board.h +++ b/hw/bsp/imxrt/boards/mimxrt1050_evkb/board.h @@ -49,4 +49,7 @@ #define UART_PORT LPUART1 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_UART_CLK_ROOT +static inline void BOARD_ConfigMPU(void) { +} + #endif diff --git a/hw/bsp/imxrt/boards/mimxrt1060_evk/board.h b/hw/bsp/imxrt/boards/mimxrt1060_evk/board.h index 5bbacadaf..e24b6dcdc 100644 --- a/hw/bsp/imxrt/boards/mimxrt1060_evk/board.h +++ b/hw/bsp/imxrt/boards/mimxrt1060_evk/board.h @@ -49,4 +49,7 @@ #define UART_PORT LPUART1 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_UART_CLK_ROOT +static inline void BOARD_ConfigMPU(void) { +} + #endif diff --git a/hw/bsp/imxrt/boards/mimxrt1064_evk/board.h b/hw/bsp/imxrt/boards/mimxrt1064_evk/board.h index 6dc01e3e7..8bdb0561b 100644 --- a/hw/bsp/imxrt/boards/mimxrt1064_evk/board.h +++ b/hw/bsp/imxrt/boards/mimxrt1064_evk/board.h @@ -49,4 +49,7 @@ #define UART_PORT LPUART1 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_UART_CLK_ROOT +static inline void BOARD_ConfigMPU(void) { +} + #endif diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h index 05bd2069f..a6332d896 100644 --- a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h +++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board.h @@ -49,14 +49,11 @@ #define UART_PORT LPUART1 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_LPUART10_CLK_ROOT -// Additional board init for MPU configuration -#define BOARD_INIT_2 1 - //-------------------------------------------------------------------- // MPU configuration //-------------------------------------------------------------------- #if __CORTEX_M == 7 -static void BOARD_ConfigMPU(void) { +static inline void BOARD_ConfigMPU(void) { #if defined(__CC_ARM) || defined(__ARMCC_VERSION) extern uint32_t Image$$RW_m_ncache$$Base[]; /* RW_m_ncache_unused is a auxiliary region which is used to get the whole size of noncache section */ @@ -434,8 +431,5 @@ static void BOARD_ConfigMPU(void) { } #endif -static void board_init2() { - BOARD_ConfigMPU(); -} #endif diff --git a/hw/bsp/imxrt/boards/teensy_40/board.h b/hw/bsp/imxrt/boards/teensy_40/board.h index ae749e894..7b8754a97 100644 --- a/hw/bsp/imxrt/boards/teensy_40/board.h +++ b/hw/bsp/imxrt/boards/teensy_40/board.h @@ -49,4 +49,7 @@ #define UART_PORT LPUART6 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_UART_CLK_ROOT +static inline void BOARD_ConfigMPU(void) { +} + #endif /* BOARD_H_ */ diff --git a/hw/bsp/imxrt/boards/teensy_41/board.h b/hw/bsp/imxrt/boards/teensy_41/board.h index 1bc022c54..91ae3debd 100644 --- a/hw/bsp/imxrt/boards/teensy_41/board.h +++ b/hw/bsp/imxrt/boards/teensy_41/board.h @@ -49,4 +49,7 @@ #define UART_PORT LPUART6 #define UART_CLK_ROOT BOARD_BOOTCLOCKRUN_UART_CLK_ROOT +static inline void BOARD_ConfigMPU(void) { +} + #endif /* BOARD_H_ */ diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c index 1bbd3400a..9cd59b7d7 100644 --- a/hw/bsp/imxrt/family.c +++ b/hw/bsp/imxrt/family.c @@ -111,10 +111,7 @@ void board_init(void) { BOARD_BootClockRUN(); SystemCoreClockUpdate(); - // Additional board init -#if defined(BOARD_INIT_2) && BOARD_INIT_2 - board_init2(); -#endif + BOARD_ConfigMPU(); // defined in board.h #ifdef TRACE_ETM //CLOCK_EnableClock(kCLOCK_Trace); From 6f06effd03d1163b3e4069d61cf158fc55eb9133 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 15 Sep 2025 16:18:07 +0700 Subject: [PATCH 382/382] add nrf54 to dwc2 info --- src/portable/synopsys/dwc2/dwc2_info.md | 116 ++++++++++++------------ src/portable/synopsys/dwc2/dwc2_info.py | 1 + 2 files changed, 59 insertions(+), 58 deletions(-) diff --git a/src/portable/synopsys/dwc2/dwc2_info.md b/src/portable/synopsys/dwc2/dwc2_info.md index e6b7820bc..f655e4dba 100644 --- a/src/portable/synopsys/dwc2/dwc2_info.md +++ b/src/portable/synopsys/dwc2/dwc2_info.md @@ -1,58 +1,58 @@ -| | AT32 F405 FS | AT32 F405 HS | AT32 F415 | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5/H7RS/N6 HS | XMC4500 | GD32VF103 | -|:---------------------------|:---------------|:---------------|:------------|:----------------|:-------------|:--------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:---------------------|:-------------|:------------| -| GUID | 0x00002000 | 0x00000000 | 0x00001000 | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00AEC000 | 0x00001000 | -| GSNPSID | 0x4F54400A | 0x4F54400A | 0x4F54400A | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54292A | 0x00000000 | -| - specs version | 4.00a | 4.00a | 4.00a | 2.80a | 3.30a | 4.00a | 4.00a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 2.92a | 0.00W | -| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | -| GHWCFG2 | 0x228FDD00 | 0x229FDDD0 | 0x228DCD00 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228F5930 | 0x00000000 | -| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | HNP SRP | HNP SRP | -| - arch | Slave only | DMA internal | Slave only | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | Slave only | -| - single_point | hub | hub | hub | hub | hub | n/a | hub | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | n/a | hub | -| - hs_phy_type | n/a | UTMI+/ULPI | n/a | UTMI+ | n/a | n/a | UTMI+/ULPI | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | n/a | n/a | -| - fs_phy_type | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Shared ULPI | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | Dedicated | n/a | -| - num_dev_ep | 7 | 7 | 3 | 7 | 6 | 6 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | -| - num_host_ch | 15 | 15 | 7 | 7 | 13 | 7 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 13 | 0 | -| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - mul_proc_intrpt | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - nptx_q_depth | 8 | 8 | 8 | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - ptx_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | -| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | -| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| GHWCFG3 | 0x020004E8 | 0x03F006E8 | 0x020004E8 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | -| - xfer_size_width | 8 | 8 | 8 | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | -| - packet_size_width | 6 | 6 | 6 | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | -| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - i2c_enable | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | -| - vendor_ctrl_itf | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | -| - optional_feature_removed | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - synch_reset | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - otg_adp_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - battery_charger_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | -| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | -| - dfifo_depth | 512 | 1008 | 512 | 4080 | 498 | 200 | 896 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 634 | 0 | -| GHWCFG4 | 0x1FF0A020 | 0x1FF0A020 | 0x0000000F | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | -| - num_dev_period_in_ep | 0 | 0 | 15 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - partial_powerdown | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - ahb_freq_min | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - enhanced_lpm_support | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | -| - phy_data_width | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8/16 bit | 8 bit | -| - ctrl_ep_num | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | -| - iddg_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - vbus_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - a_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - b_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - session_end_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | -| - dedicated_fifos | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | -| - num_dev_in_eps | 7 | 7 | 0 | 7 | 6 | 4 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | -| - dma_desc_enable | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | -| - dma_desc_dynamic | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | +| | AT32 F405 FS | AT32 F405 HS | AT32 F415 | BCM2711 (Pi4) | EFM32GG | ESP32-S2/S3 | ESP32-P4 | nRF54 | ST F207/F407/411/429 FS | ST F407/429 HS | ST F412/76x FS | ST F723/L4P5 FS | ST F723 HS | ST F76x HS | ST H743/H750 | ST L476 FS | ST U5A5/H7RS/N6 HS | XMC4500 | GD32VF103 | +|:---------------------------|:---------------|:---------------|:------------|:----------------|:-------------|:--------------|:-------------|:-------------|:--------------------------|:-----------------|:-----------------|:------------------|:-------------|:-------------|:---------------|:-------------|:---------------------|:-------------|:------------| +| GUID | 0x00002000 | 0x00000000 | 0x00001000 | 0x2708A000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00001200 | 0x00001100 | 0x00002000 | 0x00003000 | 0x00003100 | 0x00002100 | 0x00002300 | 0x00002000 | 0x00005000 | 0x00AEC000 | 0x00001000 | +| GSNPSID | 0x4F54400A | 0x4F54400A | 0x4F54400A | 0x4F54280A | 0x4F54330A | 0x4F54400A | 0x4F54400A | 0x4F54430A | 0x4F54281A | 0x4F54281A | 0x4F54320A | 0x4F54330A | 0x4F54330A | 0x4F54320A | 0x4F54330A | 0x4F54310A | 0x4F54411A | 0x4F54292A | 0x00000000 | +| - specs version | 4.00a | 4.00a | 4.00a | 2.80a | 3.30a | 4.00a | 4.00a | 4.30a | 2.81a | 2.81a | 3.20a | 3.30a | 3.30a | 3.20a | 3.30a | 3.10a | 4.11a | 2.92a | 0.00W | +| GHWCFG1 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0xAA555000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | 0x00000000 | +| GHWCFG2 | 0x228FDD00 | 0x229FDDD0 | 0x228DCD00 | 0x228DDD50 | 0x228F5910 | 0x224DD930 | 0x215FFFD0 | 0x228BFC72 | 0x229DCD20 | 0x229ED590 | 0x229ED520 | 0x229ED520 | 0x229FE1D0 | 0x229FE190 | 0x229FE190 | 0x229ED520 | 0x228FE052 | 0x228F5930 | 0x00000000 | +| - op_mode | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | HNP SRP | noHNP noSRP | HNP SRP | HNP SRP | +| - arch | Slave only | DMA internal | Slave only | DMA internal | DMA internal | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | Slave only | Slave only | DMA internal | DMA internal | DMA internal | Slave only | DMA internal | DMA internal | Slave only | +| - single_point | hub | hub | hub | hub | hub | n/a | hub | n/a | n/a | hub | n/a | n/a | hub | hub | hub | n/a | hub | n/a | hub | +| - hs_phy_type | n/a | UTMI+/ULPI | n/a | UTMI+ | n/a | n/a | UTMI+/ULPI | UTMI+ | n/a | ULPI | n/a | n/a | UTMI+/ULPI | ULPI | ULPI | n/a | UTMI+ | n/a | n/a | +| - fs_phy_type | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Shared ULPI | n/a | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | Dedicated | n/a | Dedicated | n/a | +| - num_dev_ep | 7 | 7 | 3 | 7 | 6 | 6 | 15 | 15 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | +| - num_host_ch | 15 | 15 | 7 | 7 | 13 | 7 | 15 | 15 | 7 | 11 | 11 | 11 | 15 | 15 | 15 | 11 | 15 | 13 | 0 | +| - period_channel_support | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - enable_dynamic_fifo | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - mul_proc_intrpt | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - reserved21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - nptx_q_depth | 8 | 8 | 8 | 8 | 8 | 4 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - ptx_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 4 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 2 | +| - token_q_depth | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 0 | +| - otg_enable_ic_usb | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| GHWCFG3 | 0x020004E8 | 0x03F006E8 | 0x020004E8 | 0x0FF000E8 | 0x01F204E8 | 0x00C804B5 | 0x03805EB5 | 0x0BEAC0E8 | 0x020001E8 | 0x03F403E8 | 0x0200D1E8 | 0x0200D1E8 | 0x03EED2E8 | 0x03EED2E8 | 0x03B8D2E8 | 0x0200D1E8 | 0x03B882E8 | 0x027A01E5 | 0x00000000 | +| - xfer_size_width | 8 | 8 | 8 | 8 | 8 | 5 | 5 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 8 | 5 | 0 | +| - packet_size_width | 6 | 6 | 6 | 6 | 6 | 3 | 3 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 0 | +| - otg_enable | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - i2c_enable | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | +| - vendor_ctrl_itf | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 0 | +| - optional_feature_removed | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - synch_reset | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - otg_adp_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - otg_enable_hsic | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - battery_charger_support | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | +| - lpm_mode | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | +| - dfifo_depth | 512 | 1008 | 512 | 4080 | 498 | 200 | 896 | 3050 | 512 | 1012 | 512 | 512 | 1006 | 1006 | 952 | 512 | 952 | 634 | 0 | +| GHWCFG4 | 0x1FF0A020 | 0x1FF0A020 | 0x0000000F | 0x1FF00020 | 0x1BF08030 | 0xD3F0A030 | 0xDFF1A030 | 0x1E10AA60 | 0x0FF08030 | 0x17F00030 | 0x17F08030 | 0x17F08030 | 0x23F00030 | 0x23F00030 | 0xE3F00030 | 0x17F08030 | 0xE2103E30 | 0xDBF08030 | 0x00000000 | +| - num_dev_period_in_ep | 0 | 0 | 15 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - partial_powerdown | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - ahb_freq_min | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - extended_hibernation | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - reserved8 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - enhanced_lpm_support1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - service_interval_flow | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - ipg_isoc_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - acg_support | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - enhanced_lpm_support | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | +| - phy_data_width | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8/16 bit | 8 bit | 8/16 bit | 8/16 bit | 8 bit | 8 bit | 8 bit | 8/16 bit | 8 bit | 8/16 bit | 8 bit | +| - ctrl_ep_num | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | +| - iddg_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - vbus_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - a_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - b_valid_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - session_end_filter | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | +| - dedicated_fifos | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | +| - num_dev_in_eps | 7 | 7 | 0 | 7 | 6 | 4 | 7 | 7 | 3 | 5 | 5 | 5 | 8 | 8 | 8 | 5 | 8 | 6 | 0 | +| - dma_desc_enable | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | +| - dma_desc_dynamic | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | diff --git a/src/portable/synopsys/dwc2/dwc2_info.py b/src/portable/synopsys/dwc2/dwc2_info.py index a90150632..f6bd2785a 100755 --- a/src/portable/synopsys/dwc2/dwc2_info.py +++ b/src/portable/synopsys/dwc2/dwc2_info.py @@ -16,6 +16,7 @@ dwc2_reg_value = { 'EFM32GG': [0, 0x4F54330A, 0, 0x228F5910, 0x01F204E8, 0x1BF08030], 'ESP32-S2/S3': [0, 0x4F54400A, 0, 0x224DD930, 0x0C804B5, 0xD3F0A030], 'ESP32-P4': [0, 0x4F54400A, 0, 0x215FFFD0, 0x03805EB5, 0xDFF1A030], + 'nRF54': [0, 0x4F54430A, 0xAA555000, 0x228BFC72, 0x0BEAC0E8, 0x1E10AA60], 'ST F207/F407/411/429 FS': [0x1200, 0x4F54281A, 0, 0x229DCD20, 0x020001E8, 0x0FF08030], 'ST F407/429 HS': [0x1100, 0x4F54281A, 0, 0x229ED590, 0x03F403E8, 0x17F00030], 'ST F412/76x FS': [0x2000, 0x4F54320A, 0, 0x229ED520, 0x0200D1E8, 0x17F08030],